Import Debian changes 2.1.9902-1
fusioninventory-agent (2.1.9902-1) experimental; urgency=low
* New upstream beta release
Gonéri Le Bouder authored 12 years ago
Guillaume Bougard committed 5 years ago
52 | 52 | * Add the HARDWARE/CHASSIS_TYPE information |
53 | 53 | * Linux: Use /sbin/ip to get the interface IP addresses (#854) |
54 | 54 | * HPUX: don't report unoccupied memory slots |
55 | ||
56 | 2.1.12 | |
57 | ||
58 | SOLARIS | |
59 | ✔ Fix some warnings for spurious stat() calls | |
60 | ✔ Fix hostname being forced to 'SOLARIS' | |
61 | ||
62 | 2.1.11 Mon, 12 Sep 2011 17:34:38 +0200 | |
63 | ||
64 | WINDOWS | |
65 | ✔ Fix the BIOS information collect on Win2003 <= system | |
66 | commit:8c2427da5, commit: fe345815 | |
67 | http://forge.fusioninventory.org/issues/1156 | |
55 | 68 | |
56 | 69 | 2.1.10 Tue, 06 Sep 2011 08:48:27 -0000 |
57 | 70 |
38 | 38 | lib/FusionInventory/Agent/Logger/Stderr.pm |
39 | 39 | lib/FusionInventory/Agent/Logger/Syslog.pm |
40 | 40 | lib/FusionInventory/Agent/Scheduler.pm |
41 | lib/FusionInventory/Agent/SNMP.pm | |
42 | 41 | lib/FusionInventory/Agent/Storage.pm |
43 | 42 | lib/FusionInventory/Agent/Target.pm |
44 | 43 | lib/FusionInventory/Agent/Target/Local.pm |
382 | 381 | resources/aix/README |
383 | 382 | resources/bsd/lsvfs/freebsd-8.1 |
384 | 383 | resources/bsd/mount/dragonfly-1 |
384 | resources/bsd/pkg_info/sample1 | |
385 | 385 | resources/generic/df/aix |
386 | 386 | resources/generic/df/freebsd |
387 | 387 | resources/generic/df/linux |
420 | 420 | resources/generic/ifconfig/hpux2-lan0 |
421 | 421 | resources/generic/ifconfig/linux-bonding |
422 | 422 | resources/generic/ifconfig/linux-rhel5.6 |
423 | resources/generic/ifconfig/opensolaris | |
423 | 424 | resources/generic/ifconfig/solaris-10 |
424 | 425 | resources/generic/ipmitool_lan_print/sample1 |
425 | 426 | resources/generic/lspci/dell-xt2 |
434 | 435 | resources/generic/netstat/hpux1 |
435 | 436 | resources/generic/netstat/hpux2 |
436 | 437 | resources/generic/netstat/linux1 |
438 | resources/generic/netstat/macosx1 | |
437 | 439 | resources/generic/netstat/netbsd |
438 | 440 | resources/generic/netstat/openbsd |
439 | 441 | resources/generic/ps/linux |
602 | 604 | resources/virtualization/virsh/list1 |
603 | 605 | resources/virtualization/virsh/list2 |
604 | 606 | resources/virtualization/xm/sample1 |
607 | resources/win32/printer/xppro1/USB.reg | |
608 | resources/win32/printer/xppro1/USBPRINT.reg | |
609 | resources/win32/printer/xppro2/USB.reg | |
610 | resources/win32/printer/xppro2/USBPRINT.reg | |
605 | 611 | resources/xml/response/message1.xml |
606 | 612 | resources/xml/response/message2.xml |
607 | 613 | resources/xml/response/message3.xml |
627 | 633 | t/components/inventory.t |
628 | 634 | t/components/logger.t |
629 | 635 | t/components/server.t |
630 | t/components/SNMP.t | |
631 | 636 | t/components/storage.t |
632 | 637 | t/components/target.t |
633 | 638 | t/components/task.t |
651 | 656 | t/inventory/aix/storages.t |
652 | 657 | t/inventory/aix/videos.t |
653 | 658 | t/inventory/bsd/networks.t |
659 | t/inventory/bsd/softwares.t | |
654 | 660 | t/inventory/generic/dmidecode/battery.t |
655 | 661 | t/inventory/generic/dmidecode/bios.t |
656 | 662 | t/inventory/generic/dmidecode/memory.t |
674 | 680 | t/inventory/linux/drives.t |
675 | 681 | t/inventory/linux/ilo.t |
676 | 682 | t/inventory/linux/lvm.t |
677 | t/inventory/linux/networks.t | |
678 | 683 | t/inventory/linux/rhn-systemid.t |
679 | 684 | t/inventory/linux/softwares.t |
680 | 685 | t/inventory/linux/storages/3ware.t |
690 | 695 | t/inventory/virtualization/parallels.t |
691 | 696 | t/inventory/virtualization/virtualbox.t |
692 | 697 | t/inventory/virtualization/xen.t |
698 | t/inventory/win32/printer/xppro1/USB.reg | |
699 | t/inventory/win32/printer/xppro1/USBPRINT.reg | |
700 | t/inventory/win32/printer/xppro2/USB.reg | |
701 | t/inventory/win32/printer/xppro2/USBPRINT.reg | |
693 | 702 | t/perlcriticrc |
694 | 703 | t/ssl/cnf/alternate.cnf |
695 | 704 | t/ssl/cnf/bad.cnf |
4 | 4 | HTTP::Proxy: 0 |
5 | 5 | HTTP::Server::Simple: 0 |
6 | 6 | HTTP::Server::Simple::Authen: 0 |
7 | HTTP::Server::Simple::CGI: 0 | |
8 | 7 | IO::Capture::Stderr: 0 |
9 | 8 | IPC::Run: 0 |
10 | 9 | Test::Exception: 0 |
11 | Test::More: 0 | |
10 | Test::More: 0.93 | |
12 | 11 | YAML: 0 |
13 | 12 | configure_requires: |
14 | 13 | ExtUtils::MakeMaker: 6.42 |
15 | 14 | distribution_type: module |
16 | generated_by: 'Module::Install version 1.01' | |
15 | generated_by: 'Module::Install version 1.02' | |
17 | 16 | license: gpl |
18 | 17 | meta-spec: |
19 | 18 | url: http://module-build.sourceforge.net/META-spec-v1.4.html |
42 | 41 | perl: 5.8.0 |
43 | 42 | resources: |
44 | 43 | license: http://opensource.org/licenses/gpl-license.php |
45 | version: 2.1.9901 | |
44 | version: 2.1.9902 |
36 | 36 | } |
37 | 37 | |
38 | 38 | # test dependencies |
39 | test_requires 'Test::More' => undef; | |
39 | test_requires 'Test::More' => '0.93'; # subtest | |
40 | 40 | test_requires 'IPC::Run' => undef; |
41 | 41 | test_requires 'HTTP::Proxy' => undef; |
42 | 42 | test_requires 'HTTP::Server::Simple' => undef; |
43 | test_requires 'HTTP::Server::Simple::CGI' => undef; | |
44 | 43 | test_requires 'HTTP::Server::Simple::Authen' => undef; |
45 | 44 | test_requires 'IO::Capture::Stderr' => undef; |
46 | 45 | test_requires 'Test::Exception' => undef; |
49 | 48 | install_script 'fusioninventory-agent'; |
50 | 49 | install_script 'fusioninventory-win32-service' if $OSNAME eq 'MSWin32'; |
51 | 50 | install_script 'fusioninventory-injector'; |
52 | ||
53 | 51 | # memconf is needed by Solaris backend module |
54 | if ($OSNAME eq 'solaris') { | |
55 | install_script 'memconf'; | |
56 | } | |
52 | install_script 'memconf' if $OSNAME eq 'solaris'; | |
57 | 53 | |
58 | 54 | makemaker_args( |
59 | 55 | test => { |
63 | 59 | |
64 | 60 | WriteAll; |
65 | 61 | |
62 | # substitute prefix everywhere | |
63 | $MY::variables{SYSCONFDIR} =~ s/\$\(PREFIX\)/$MY::variables{PREFIX}/; | |
64 | $MY::variables{DATADIR} =~ s/\$\(PREFIX\)/$MY::variables{PREFIX}/; | |
65 | $MY::variables{LOCALSTATEDIR} =~ s/\$\(PREFIX\)/$MY::variables{PREFIX}/; | |
66 | ||
67 | # look for already existing configuration file | |
68 | my $config_file_message = -f "$MY::variables{SYSCONFDIR}/agent.cfg" ? | |
69 | "previous configuration file found, new one will be installed as agent.cfg.new" : | |
70 | "no previous configuration file found, new one will be installed as agent.cfg"; | |
71 | ||
66 | 72 | print <<EOF; |
67 | 73 | |
68 | 74 | Installation summary |
69 | 75 | -------------------- |
70 | ||
71 | 76 | prefix: $MY::variables{PREFIX} |
72 | 77 | configuration installation directory: $MY::variables{SYSCONFDIR} |
73 | 78 | constant data installation directory: $MY::variables{DATADIR} |
74 | 79 | variable data installation directory: $MY::variables{LOCALSTATEDIR} |
75 | 80 | |
81 | $config_file_message | |
76 | 82 | EOF |
77 | 83 | |
78 | 84 | package MY; |
88 | 94 | # for some reason, initialising variables from the global scope doesn't work |
89 | 95 | %variables = ( |
90 | 96 | PREFIX => '/usr/local', |
91 | INSTALLBIN => '$(PREFIX)/bin', | |
92 | INSTALLSITEBIN => '$(PREFIX)/bin', | |
93 | INSTALLVENDORBIN => '$(PREFIX)/bin', | |
97 | INSTALLSCRIPT => '$(PREFIX)/bin', | |
98 | INSTALLSITESCRIPT => '$(PREFIX)/bin', | |
99 | INSTALLVENDORSCRIPT => '$(PREFIX)/bin', | |
94 | 100 | INSTALLMAN1DIR => '$(PREFIX)/share/man/man1', |
95 | 101 | INSTALLSITEMAN1DIR => '$(PREFIX)/share/man/man1', |
96 | 102 | INSTALLVENDORMAN1DIR => '$(PREFIX)/share/man/man1', |
110 | 116 | # Skip comments |
111 | 117 | next if $line =~ /^\s*#/; |
112 | 118 | # Skip everything which isn't a var assignment. |
113 | next unless $line =~ /^([A-Z_]+) =/; | |
119 | next unless $line =~ /^([A-Z0-9_]+) =/; | |
114 | 120 | my $name = $1; |
115 | 121 | # skip variables we're not interested |
116 | 122 | next unless $variables{$name}; |
0 | This package uses quilt to manage all modifications to the upstream | |
1 | source. Changes are stored in the source package as diffs in | |
2 | debian/patches and applied during the build. | |
3 | ||
4 | To configure quilt to use debian/patches instead of patches, you want | |
5 | either to export QUILT_PATCHES=debian/patches in your environment | |
6 | or use this snippet in your ~/.quiltrc: | |
7 | ||
8 | for where in ./ ../ ../../ ../../../ ../../../../ ../../../../../; do | |
9 | if [ -e ${where}debian/rules -a -d ${where}debian/patches ]; then | |
10 | export QUILT_PATCHES=debian/patches | |
11 | break | |
12 | fi | |
13 | done | |
14 | ||
15 | To get the fully patched source after unpacking the source package, cd to | |
16 | the root level of the source package and run: | |
17 | ||
18 | quilt push -a | |
19 | ||
20 | The last patch listed in debian/patches/series will become the current | |
21 | patch. | |
22 | ||
23 | To add a new set of changes, first run quilt push -a, and then run: | |
24 | ||
25 | quilt new <patch> | |
26 | ||
27 | where <patch> is a descriptive name for the patch, used as the filename in | |
28 | debian/patches. Then, for every file that will be modified by this patch, | |
29 | run: | |
30 | ||
31 | quilt add <file> | |
32 | ||
33 | before editing those files. You must tell quilt with quilt add what files | |
34 | will be part of the patch before making changes or quilt will not work | |
35 | properly. After editing the files, run: | |
36 | ||
37 | quilt refresh | |
38 | ||
39 | to save the results as a patch. | |
40 | ||
41 | Alternately, if you already have an external patch and you just want to | |
42 | add it to the build system, run quilt push -a and then: | |
43 | ||
44 | quilt import -P <patch> /path/to/patch | |
45 | quilt push -a | |
46 | ||
47 | (add -p 0 to quilt import if needed). <patch> as above is the filename to | |
48 | use in debian/patches. The last quilt push -a will apply the patch to | |
49 | make sure it works properly. | |
50 | ||
51 | To remove an existing patch from the list of patches that will be applied, | |
52 | run: | |
53 | ||
54 | quilt delete <patch> | |
55 | ||
56 | You may need to run quilt pop -a to unapply patches first before running | |
57 | this command. |
0 | fusioninventory-agent (2.1.9902-1) experimental; urgency=low | |
1 | ||
2 | * New upstream beta release | |
3 | ||
4 | -- Gonéri Le Bouder <goneri@rulezlan.org> Fri, 21 Oct 2011 17:51:50 +0200 | |
5 | ||
0 | 6 | fusioninventory-agent (2.1.9901-2) experimental; urgency=low |
1 | 7 | |
2 | 8 | * Restore the B-D, sorry |
21 | 21 | Package: fusioninventory-agent |
22 | 22 | Architecture: any |
23 | 23 | Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, |
24 | ucf, libxml-simple-perl, | |
25 | libnet-ip-perl, libcompress-zlib-perl, libwww-perl, libnet-ssleay-perl, | |
24 | ucf, libnet-ip-perl, libcompress-zlib-perl, libwww-perl, libnet-ssleay-perl, | |
26 | 25 | libproc-daemon-perl, dmidecode [amd64 i386 ia64 kfreebsd-amd64 kfreebsd-i386], |
27 | libuniversal-require-perl, libproc-pid-file-perl, hdparm, libhttp-daemon-perl, | |
26 | libuniversal-require-perl, libproc-pid-file-perl, hdparm, | |
28 | 27 | libfile-which-perl, libxml-treepp-perl, libyaml-perl, libtext-template-perl, |
29 | 28 | libjson-perl, |
29 | # LWP 6 | |
30 | libhttp-daemon-perl, | |
30 | 31 | Suggests: pciutils, smartmontools, read-edid |
31 | 32 | Description: Hardware and software inventory tool (client) |
32 | 33 | FusionInventory Agent is an application designed to help a network |
0 | 0 | --- fusioninventory-agent.orig/Makefile.PL |
1 | 1 | +++ fusioninventory-agent/Makefile.PL |
2 | @@ -95,9 +95,9 @@ | |
2 | @@ -94,16 +94,16 @@ | |
3 | ||
4 | # for some reason, initialising variables from the global scope doesn't work | |
5 | %variables = ( | |
6 | - PREFIX => '/usr/local', | |
7 | + PREFIX => '/usr', | |
8 | INSTALLSCRIPT => '$(PREFIX)/bin', | |
9 | INSTALLSITESCRIPT => '$(PREFIX)/bin', | |
10 | INSTALLVENDORSCRIPT => '$(PREFIX)/bin', | |
3 | 11 | INSTALLMAN1DIR => '$(PREFIX)/share/man/man1', |
4 | 12 | INSTALLSITEMAN1DIR => '$(PREFIX)/share/man/man1', |
5 | 13 | INSTALLVENDORMAN1DIR => '$(PREFIX)/share/man/man1', |
7 | 15 | + SYSCONFDIR => '/etc/fusioninventory', |
8 | 16 | DATADIR => '$(PREFIX)/share/fusioninventory', |
9 | 17 | - LOCALSTATEDIR => '$(PREFIX)/var/fusioninventory', |
10 | + LOCALSTATEDIR => '/var/fusioninventory', | |
18 | + LOCALSTATEDIR => '/var/lib/fusioninventory-agent', | |
11 | 19 | ); |
12 | 20 | |
13 | 21 | # allow variables defined on command line to override defaults |
0 | 0 | #!/usr/bin/make -f |
1 | 1 | |
2 | BACKPORT = "no" | |
2 | BACKPORT = no | |
3 | 3 | |
4 | 4 | %: |
5 | dh $@ | |
5 | dh $@ --with quilt | |
6 | 6 | |
7 | 7 | override_dh_auto_clean: |
8 | 8 | [ ! -d var ] || rm -r var |
0 | #!/bin/sh | |
1 | ||
2 | VERSION=`dpkg-parsechangelog | awk '/Version/ {print $2}'` | |
3 | UBUREV=1 | |
4 | ||
5 | echo $VERSION | |
6 | ||
7 | for dist in natty maverick lucid hardy; do | |
8 | git checkout HEAD -- debian/changelog | |
9 | dch --force-distribution -v $VERSION$dist$UBUREV -D $dist "Backport for $dist" | |
10 | dpkg-buildpackage -S -D -sa -i.git | |
11 | dput ppa ../fusioninventory-agent_$VERSION$dist${UBUREV}_source.changes | |
12 | done |
10 | 10 | # send tasks results to an OCS server |
11 | 11 | #server = http://server.domain.com/ocsinventory |
12 | 12 | # send tasks results to a FusionInventory for GLPI server |
13 | #server = http://server.domain.com/glpi/plugins/fusioninventory/front/plugin_fusioninventory.communication.php | |
13 | #server = http://server.domain.com/glpi/plugins/fusioninventory/ | |
14 | 14 | # write tasks results in a directory |
15 | 15 | #local = /tmp |
16 | 16 | # write tasks results on stdout |
21 | 21 | # |
22 | 22 | |
23 | 23 | # disable software deployment tasks |
24 | #no-task = deploy,ocsdeploy | |
24 | #no-task = deploy | |
25 | 25 | |
26 | 26 | # |
27 | 27 | # Target scheduling options |
76 | 76 | exit 0; |
77 | 77 | } |
78 | 78 | |
79 | my $agent = FusionInventory::Agent->new( | |
80 | confdir => './etc', | |
81 | datadir => './share', | |
82 | vardir => './var', | |
83 | ); | |
84 | ||
79 | 85 | if ($options->{'list-tasks'}) { |
80 | my %tasks = FusionInventory::Agent->getKnownTasks(); | |
86 | my %tasks = $agent->getAvailableTasks(); | |
81 | 87 | foreach my $task (keys %tasks) { |
82 | 88 | print "$task (v$tasks{$task})\n"; |
83 | 89 | } |
85 | 91 | } |
86 | 92 | |
87 | 93 | eval { |
88 | my $agent = FusionInventory::Agent->new( | |
89 | confdir => './etc', | |
90 | datadir => './share', | |
91 | vardir => './var', | |
92 | options => $options | |
93 | ); | |
94 | $agent->init(options => $options); | |
94 | 95 | $agent->run(); |
95 | 96 | }; |
96 | 97 | |
99 | 100 | print STDERR $EVAL_ERROR; |
100 | 101 | exit 1; |
101 | 102 | } |
103 | ||
104 | exit(0); | |
102 | 105 | |
103 | 106 | __END__ |
104 | 107 |
0 | 0 | #!/usr/bin/perl |
1 | BEGIN { | |
2 | use File::Spec; | |
3 | use File::Basename; | |
4 | chdir(dirname(File::Spec->rel2abs( __FILE__ ))."/../.."); | |
5 | } | |
6 | 1 | |
7 | 2 | use strict; |
8 | 3 | use warnings; |
9 | 4 | use lib './lib'; |
10 | 5 | use threads; |
11 | 6 | use threads::shared; |
7 | use constant SERVICE_SLEEP_TIME => 2000; # 20 milliseconds | |
8 | ||
9 | use File::Spec; | |
10 | use File::Basename; | |
12 | 11 | |
13 | 12 | use English qw(-no_match_vars); |
14 | 13 | use Win32; |
19 | 18 | delete($ENV{PERL5LIB}); |
20 | 19 | delete($ENV{PERLLIB}); |
21 | 20 | |
21 | my $directory = dirname(File::Spec->rel2abs( __FILE__ )); | |
22 | # on Win2k, Windows do not chdir to the bin directory | |
23 | # we need to do it by ourself | |
24 | chdir($directory); | |
25 | ||
22 | 26 | my $win32service = 1; |
23 | 27 | Win32::Daemon::StartService(); |
24 | my $SERVICE_SLEEP_TIME = 2000; # 20 milliseconds | |
25 | my $PrevState = SERVICE_START_PENDING; | |
26 | 28 | |
27 | my $thr; | |
29 | my $thread; | |
28 | 30 | |
29 | sub startAgent { | |
30 | return if $thr; | |
31 | $thr = threads->create(sub { | |
32 | my $agent = new FusionInventory::Agent( | |
33 | confdir => './etc/fusioninventory', | |
34 | datadir => './share', | |
35 | vardir => './var', | |
36 | options => { | |
37 | service => 1 | |
38 | } | |
39 | ); | |
40 | $agent->run(); | |
41 | }); | |
31 | sub getMessage { | |
32 | ||
33 | if ($Win32::Daemon::VERSION < 20101014) { | |
34 | return Win32::Daemon::LastControlMessage(1); | |
35 | } else { | |
36 | return Win32::Daemon::QueryLastMessage(); | |
37 | } | |
42 | 38 | } |
43 | 39 | |
44 | sub killAgent { | |
45 | $thr->kill('KILL'); | |
46 | $thr = undef; | |
47 | } | |
48 | ||
49 | my $State; | |
50 | while (SERVICE_STOPPED != ($State = Win32::Daemon::State())){ | |
51 | if (SERVICE_START_PENDING == $State) { | |
40 | my $state; | |
41 | my $previousState = SERVICE_START_PENDING; | |
42 | while (($state = Win32::Daemon::State()) != SERVICE_STOPPED) { | |
43 | if ($state == SERVICE_START_PENDING) { | |
52 | 44 | # Initialization code |
53 | 45 | startAgent(); |
54 | 46 | Win32::Daemon::State(SERVICE_RUNNING); |
55 | $PrevState = SERVICE_RUNNING; | |
56 | } elsif (SERVICE_STOP_PENDING == $State) { | |
47 | $previousState = SERVICE_RUNNING; | |
48 | } elsif ($state == SERVICE_STOP_PENDING) { | |
57 | 49 | killAgent(); |
58 | 50 | Win32::Daemon::State(SERVICE_STOPPED); |
59 | } elsif (SERVICE_PAUSE_PENDING == $State) { | |
51 | } elsif ($state == SERVICE_PAUSE_PENDING) { | |
60 | 52 | # "Pausing..."; |
61 | 53 | killAgent(); |
62 | 54 | Win32::Daemon::State(SERVICE_PAUSED); |
63 | $PrevState = SERVICE_PAUSED; | |
55 | $previousState = SERVICE_PAUSED; | |
64 | 56 | killAgent(); |
65 | 57 | next; |
66 | } elsif (SERVICE_CONTINUE_PENDING == $State) { | |
58 | } elsif ($state == SERVICE_CONTINUE_PENDING) { | |
67 | 59 | # "Resuming..."; |
68 | 60 | startAgent(); |
69 | 61 | Win32::Daemon::State(SERVICE_RUNNING); |
70 | $PrevState = SERVICE_RUNNING; | |
62 | $previousState = SERVICE_RUNNING; | |
71 | 63 | next; |
72 | } elsif (SERVICE_STOP_PENDING == $State) { | |
64 | } elsif ($state == SERVICE_STOP_PENDING) { | |
73 | 65 | # "Stopping..."; |
74 | 66 | killAgent(); |
75 | 67 | Win32::Daemon::State(SERVICE_STOPPED); |
76 | $PrevState = SERVICE_STOPPED; | |
68 | $previousState = SERVICE_STOPPED; | |
77 | 69 | next; |
78 | } elsif (SERVICE_RUNNING == $State) { | |
70 | } elsif ($state == SERVICE_RUNNING) { | |
79 | 71 | # The service is running as normal... |
80 | 72 | # ...add the main code here... |
81 | 73 | startAgent(); |
82 | 74 | } else { |
83 | 75 | # Got an unhandled control message. Set the state to |
84 | 76 | # whatever the previous state was. |
85 | Win32::Daemon::State($PrevState); | |
77 | Win32::Daemon::State($previousState); | |
86 | 78 | } |
87 | 79 | |
88 | 80 | # Check for any outstanding commands. Pass in a non zero value |
89 | 81 | # and it resets the Last Message to SERVICE_CONTROL_NONE. |
90 | if (SERVICE_CONTROL_NONE != (my $Message = | |
91 | Win32::Daemon::LastControlMessage(1))) { | |
92 | if (SERVICE_CONTROL_INTERROGATE == $Message) { | |
82 | if (SERVICE_CONTROL_NONE != (my $message = getMessage())) { | |
83 | if (SERVICE_CONTROL_INTERROGATE == $message) { | |
93 | 84 | # Got here if the Service Control Manager is requesting |
94 | 85 | # the current state of the service. This can happen for |
95 | 86 | # a variety of reasons. Report the last state we set. |
96 | Win32::Daemon::State( $PrevState ); | |
97 | } elsif (SERVICE_CONTROL_SHUTDOWN == $Message) { | |
87 | Win32::Daemon::State($previousState); | |
88 | } elsif (SERVICE_CONTROL_SHUTDOWN == $message) { | |
98 | 89 | # Yikes! The system is shutting down. We had better clean up |
99 | 90 | # and stop. |
100 | 91 | # Tell the SCM that we are preparing to shutdown and that we expect |
104 | 95 | } |
105 | 96 | } |
106 | 97 | # Snoose for awhile so we don't suck up cpu time... |
107 | Win32::Sleep($SERVICE_SLEEP_TIME); | |
98 | Win32::Sleep(SERVICE_SLEEP_TIME); | |
99 | } | |
100 | ||
101 | sub startAgent { | |
102 | return if $thread; | |
103 | $thread = threads->create(sub { | |
104 | my $agent = new FusionInventory::Agent( | |
105 | confdir => $directory . '/../../etc/fusioninventory', | |
106 | datadir => $directory . '/../../share', | |
107 | vardir => $directory . '/../../var', | |
108 | ); | |
109 | $agent->init(options => { service => 1 }); | |
110 | $agent->run(); | |
111 | }); | |
112 | } | |
113 | ||
114 | sub killAgent { | |
115 | $thread->kill('KILL'); | |
116 | $thread = undef; | |
108 | 117 | } |
109 | 118 | |
110 | 119 | __END__ |
16 | 16 | ); |
17 | 17 | |
18 | 18 | # various lexical flags |
19 | my ( @Missing, @Existing, %DisabledTests, $UnderCPAN, $HasCPANPLUS ); | |
19 | my ( @Missing, @Existing, %DisabledTests, $UnderCPAN, $InstallDepsTarget, $HasCPANPLUS ); | |
20 | 20 | my ( |
21 | $Config, $CheckOnly, $SkipInstall, $AcceptDefault, $TestOnly, $AllDeps | |
21 | $Config, $CheckOnly, $SkipInstall, $AcceptDefault, $TestOnly, $AllDeps, | |
22 | $UpgradeDeps | |
22 | 23 | ); |
23 | my ( $PostambleActions, $PostambleUsed ); | |
24 | my ( $PostambleActions, $PostambleActionsNoTest, $PostambleActionsUpgradeDeps, | |
25 | $PostambleActionsUpgradeDepsNoTest, $PostambleActionsListDeps, | |
26 | $PostambleActionsListAllDeps, $PostambleUsed, $NoTest); | |
24 | 27 | |
25 | 28 | # See if it's a testing or non-interactive session |
26 | 29 | _accept_default( $ENV{AUTOMATED_TESTING} or ! -t STDIN ); |
28 | 31 | |
29 | 32 | sub _accept_default { |
30 | 33 | $AcceptDefault = shift; |
34 | } | |
35 | ||
36 | sub _installdeps_target { | |
37 | $InstallDepsTarget = shift; | |
31 | 38 | } |
32 | 39 | |
33 | 40 | sub missing_modules { |
62 | 69 | __PACKAGE__->install( $Config, @Missing = split( /,/, $1 ) ); |
63 | 70 | exit 0; |
64 | 71 | } |
72 | elsif ( $arg =~ /^--upgradedeps=(.*)$/ ) { | |
73 | $UpgradeDeps = 1; | |
74 | __PACKAGE__->install( $Config, @Missing = split( /,/, $1 ) ); | |
75 | exit 0; | |
76 | } | |
65 | 77 | elsif ( $arg =~ /^--default(?:deps)?$/ ) { |
66 | 78 | $AcceptDefault = 1; |
67 | 79 | } |
124 | 136 | # check entirely since we don't want to have to load (and configure) |
125 | 137 | # an old CPAN just for a cosmetic message |
126 | 138 | |
127 | $UnderCPAN = _check_lock(1) unless $SkipInstall; | |
139 | $UnderCPAN = _check_lock(1) unless $SkipInstall || $InstallDepsTarget; | |
128 | 140 | |
129 | 141 | while ( my ( $feature, $modules ) = splice( @args, 0, 2 ) ) { |
130 | 142 | my ( @required, @tests, @skiptests ); |
206 | 218 | $CheckOnly |
207 | 219 | or ($mandatory and $UnderCPAN) |
208 | 220 | or $AllDeps |
221 | or $InstallDepsTarget | |
209 | 222 | or _prompt( |
210 | 223 | qq{==> Auto-install the } |
211 | 224 | . ( @required / 2 ) |
236 | 249 | } |
237 | 250 | } |
238 | 251 | |
239 | if ( @Missing and not( $CheckOnly or $UnderCPAN ) ) { | |
252 | if ( @Missing and not( $CheckOnly or $UnderCPAN) ) { | |
240 | 253 | require Config; |
241 | ||
242 | "*** Dependencies will be installed the next time you type '$Config::Config{make}'.\n"; | |
254 | my $make = $Config::Config{make}; | |
255 | if ($InstallDepsTarget) { | |
256 | ||
257 | "*** To install dependencies type '$make installdeps' or '$make installdeps_notest'.\n"; | |
258 | } | |
259 | else { | |
260 | ||
261 | "*** Dependencies will be installed the next time you type '$make'.\n"; | |
262 | } | |
243 | 263 | |
244 | 264 | # make an educated guess of whether we'll need root permission. |
245 | 265 | print " (You may need to do that as the 'root' user.)\n" |
270 | 290 | sub _check_lock { |
271 | 291 | return unless @Missing or @_; |
272 | 292 | |
293 | if ($ENV{PERL5_CPANM_IS_RUNNING}) { | |
294 | return _running_under('cpanminus'); | |
295 | } | |
296 | ||
273 | 297 | my $cpan_env = $ENV{PERL5_CPAN_IS_RUNNING}; |
274 | 298 | |
275 | 299 | if ($ENV{PERL5_CPANPLUS_IS_RUNNING}) { |
329 | 353 | else { |
330 | 354 | push @modules, $pkg, $ver; |
331 | 355 | } |
356 | } | |
357 | ||
358 | if ($UpgradeDeps) { | |
359 | push @modules, @installed; | |
360 | @installed = (); | |
332 | 361 | } |
333 | 362 | |
334 | 363 | return @installed unless @modules; # nothing to do |
462 | 491 | } else { |
463 | 492 | die "*** Cannot convert option $key = '$value' to CPANPLUS version.\n"; |
464 | 493 | } |
494 | push @config, 'prereqs', $value; | |
495 | } elsif ( $key eq 'force' ) { | |
496 | push @config, $key, $value; | |
497 | } elsif ( $key eq 'notest' ) { | |
498 | push @config, 'skiptest', $value; | |
465 | 499 | } else { |
466 | 500 | die "*** Cannot convert option $key to CPANPLUS version.\n"; |
467 | 501 | } |
496 | 530 | # set additional options |
497 | 531 | while ( my ( $opt, $arg ) = splice( @config, 0, 2 ) ) { |
498 | 532 | ( $args{$opt} = $arg, next ) |
499 | if $opt =~ /^force$/; # pseudo-option | |
533 | if $opt =~ /^(?:force|notest)$/; # pseudo-option | |
500 | 534 | $CPAN::Config->{$opt} = $arg; |
535 | } | |
536 | ||
537 | if ($args{notest} && (not CPAN::Shell->can('notest'))) { | |
538 | die "Your version of CPAN is too old to support the 'notest' pragma"; | |
501 | 539 | } |
502 | 540 | |
503 | 541 | local $CPAN::Config->{prerequisites_policy} = 'follow'; |
518 | 556 | delete $INC{$inc}; |
519 | 557 | } |
520 | 558 | |
521 | my $rv = $args{force} ? CPAN::Shell->force( install => $pkg ) | |
522 | : CPAN::Shell->install($pkg); | |
559 | my $rv = do { | |
560 | if ($args{force}) { | |
561 | CPAN::Shell->force( install => $pkg ) | |
562 | } elsif ($args{notest}) { | |
563 | CPAN::Shell->notest( install => $pkg ) | |
564 | } else { | |
565 | CPAN::Shell->install($pkg) | |
566 | } | |
567 | }; | |
568 | ||
523 | 569 | $rv ||= eval { |
524 | 570 | $CPAN::META->instance( 'CPAN::Distribution', $obj->cpan_file, ) |
525 | 571 | ->{install} |
762 | 808 | : "\$(NOECHO) \$(NOOP)" |
763 | 809 | ); |
764 | 810 | |
811 | my $deps_list = join( ',', @Missing, @Existing ); | |
812 | ||
813 | $PostambleActionsUpgradeDeps = | |
814 | "\$(PERL) $0 --config=$config --upgradedeps=$deps_list"; | |
815 | ||
816 | my $config_notest = | |
817 | join( ',', (UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config}), | |
818 | 'notest', 1 ) | |
819 | if $Config; | |
820 | ||
821 | $PostambleActionsNoTest = ( | |
822 | ($missing and not $UnderCPAN) | |
823 | ? "\$(PERL) $0 --config=$config_notest --installdeps=$missing" | |
824 | : "\$(NOECHO) \$(NOOP)" | |
825 | ); | |
826 | ||
827 | $PostambleActionsUpgradeDepsNoTest = | |
828 | "\$(PERL) $0 --config=$config_notest --upgradedeps=$deps_list"; | |
829 | ||
830 | $PostambleActionsListDeps = | |
831 | '@$(PERL) -le "print for @ARGV" ' | |
832 | . join(' ', map $Missing[$_], grep $_ % 2 == 0, 0..$#Missing); | |
833 | ||
834 | my @all = (@Missing, @Existing); | |
835 | ||
836 | $PostambleActionsListAllDeps = | |
837 | '@$(PERL) -le "print for @ARGV" ' | |
838 | . join(' ', map $all[$_], grep $_ % 2 == 0, 0..$#all); | |
839 | ||
765 | 840 | return %args; |
766 | 841 | } |
767 | 842 | |
796 | 871 | |
797 | 872 | sub postamble { |
798 | 873 | $PostambleUsed = 1; |
799 | ||
800 | return <<"END_MAKE"; | |
874 | my $fragment; | |
875 | ||
876 | $fragment .= <<"AUTO_INSTALL" if !$InstallDepsTarget; | |
801 | 877 | |
802 | 878 | config :: installdeps |
803 | 879 | \t\$(NOECHO) \$(NOOP) |
880 | AUTO_INSTALL | |
881 | ||
882 | $fragment .= <<"END_MAKE"; | |
804 | 883 | |
805 | 884 | checkdeps :: |
806 | 885 | \t\$(PERL) $0 --checkdeps |
808 | 887 | installdeps :: |
809 | 888 | \t$PostambleActions |
810 | 889 | |
890 | installdeps_notest :: | |
891 | \t$PostambleActionsNoTest | |
892 | ||
893 | upgradedeps :: | |
894 | \t$PostambleActionsUpgradeDeps | |
895 | ||
896 | upgradedeps_notest :: | |
897 | \t$PostambleActionsUpgradeDepsNoTest | |
898 | ||
899 | listdeps :: | |
900 | \t$PostambleActionsListDeps | |
901 | ||
902 | listalldeps :: | |
903 | \t$PostambleActionsListAllDeps | |
904 | ||
811 | 905 | END_MAKE |
812 | 906 | |
907 | return $fragment; | |
813 | 908 | } |
814 | 909 | |
815 | 910 | 1; |
816 | 911 | |
817 | 912 | __END__ |
818 | 913 | |
819 | #line 1071 | |
914 | #line 1178 |
3 | 3 | use strict 'vars'; |
4 | 4 | use vars qw{$VERSION}; |
5 | 5 | BEGIN { |
6 | $VERSION = '1.01'; | |
6 | $VERSION = '1.02'; | |
7 | 7 | } |
8 | 8 | |
9 | 9 | # Suspend handler for "redefined" warnings |
8 | 8 | |
9 | 9 | use vars qw{$VERSION @ISA $ISCORE}; |
10 | 10 | BEGIN { |
11 | $VERSION = '1.01'; | |
11 | $VERSION = '1.02'; | |
12 | 12 | @ISA = 'Module::Install::Base'; |
13 | 13 | $ISCORE = 1; |
14 | 14 | } |
5 | 5 | |
6 | 6 | use vars qw{$VERSION @ISA $ISCORE}; |
7 | 7 | BEGIN { |
8 | $VERSION = '1.01'; | |
8 | $VERSION = '1.02'; | |
9 | 9 | @ISA = 'Module::Install::Base'; |
10 | 10 | $ISCORE = 1; |
11 | 11 | } |
5 | 5 | |
6 | 6 | use vars qw{$VERSION @ISA $ISCORE}; |
7 | 7 | BEGIN { |
8 | $VERSION = '1.01'; | |
8 | $VERSION = '1.02'; | |
9 | 9 | @ISA = 'Module::Install::Base'; |
10 | 10 | $ISCORE = 1; |
11 | 11 | } |
7 | 7 | |
8 | 8 | use vars qw{$VERSION @ISA $ISCORE}; |
9 | 9 | BEGIN { |
10 | $VERSION = '1.01'; | |
10 | $VERSION = '1.02'; | |
11 | 11 | @ISA = 'Module::Install::Base'; |
12 | 12 | $ISCORE = 1; |
13 | 13 | } |
5 | 5 | |
6 | 6 | use vars qw{$VERSION @ISA $ISCORE}; |
7 | 7 | BEGIN { |
8 | $VERSION = '1.01'; | |
8 | $VERSION = '1.02'; | |
9 | 9 | @ISA = 'Module::Install::Base'; |
10 | 10 | $ISCORE = 1; |
11 | 11 | } |
169 | 169 | # Normalize the version |
170 | 170 | $version = $self->_perl_version($version); |
171 | 171 | |
172 | # We don't support the reall old versions | |
172 | # We don't support the really old versions | |
173 | 173 | unless ( $version >= 5.005 ) { |
174 | 174 | die "Module::Install only supports 5.005 or newer (use ExtUtils::MakeMaker)\n"; |
175 | 175 | } |
581 | 581 | sub requires_from { |
582 | 582 | my $self = shift; |
583 | 583 | my $content = Module::Install::_readperl($_[0]); |
584 | my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+([\d\.]+)/mg; | |
584 | my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+(v?[\d\.]+)/mg; | |
585 | 585 | while ( @requires ) { |
586 | 586 | my $module = shift @requires; |
587 | 587 | my $version = shift @requires; |
5 | 5 | |
6 | 6 | use vars qw{$VERSION @ISA $ISCORE}; |
7 | 7 | BEGIN { |
8 | $VERSION = '1.01'; | |
8 | $VERSION = '1.02'; | |
9 | 9 | @ISA = 'Module::Install::Base'; |
10 | 10 | $ISCORE = 1; |
11 | 11 | } |
5 | 5 | |
6 | 6 | use vars qw{$VERSION @ISA $ISCORE}; |
7 | 7 | BEGIN { |
8 | $VERSION = '1.01'; | |
8 | $VERSION = '1.02'; | |
9 | 9 | @ISA = 'Module::Install::Base'; |
10 | 10 | $ISCORE = 1; |
11 | 11 | } |
5 | 5 | |
6 | 6 | use vars qw{$VERSION @ISA $ISCORE}; |
7 | 7 | BEGIN { |
8 | $VERSION = '1.01'; | |
8 | $VERSION = '1.02'; | |
9 | 9 | @ISA = qw{Module::Install::Base}; |
10 | 10 | $ISCORE = 1; |
11 | 11 | } |
30 | 30 | # This is not enforced yet, but will be some time in the next few |
31 | 31 | # releases once we can make sure it won't clash with custom |
32 | 32 | # Module::Install extensions. |
33 | $VERSION = '1.01'; | |
33 | $VERSION = '1.02'; | |
34 | 34 | |
35 | 35 | # Storage for the pseudo-singleton |
36 | 36 | $MAIN = undef; |
11 | 11 | 'logger' => 'Stderr', |
12 | 12 | 'logfacility' => 'LOG_USER', |
13 | 13 | 'delaytime' => 3600, |
14 | 'backend-collect-timeout' => 180, | |
14 | 'backend-collect-timeout' => 30, | |
15 | 15 | 'httpd-port' => 62354, |
16 | 16 | }; |
17 | 17 |
33 | 33 | $self->{ua}->default_header('Content-type' => 'application/x-compress'); |
34 | 34 | $self->{logger}->debug( |
35 | 35 | $log_prefix . |
36 | 'Using gzip for compression (server minimal version 1.02 needed)' | |
36 | 'Using gzip for compression' | |
37 | 37 | ); |
38 | 38 | } else { |
39 | 39 | $self->{compression} = 'none'; |
40 | 40 | $self->{logger}->debug( |
41 | 41 | $log_prefix . |
42 | 'Not using compression (server minimal version 1.02 needed)' | |
42 | 'Not using compression' | |
43 | 43 | ); |
44 | 44 | } |
45 | 45 | |
120 | 120 | if ($data =~ /(\x78\x9C.*)/s) { |
121 | 121 | $self->{logger}->debug2("format: Zlib"); |
122 | 122 | return $self->_uncompressNative($1); |
123 | } elsif ($data =~ /(\x1F\x8B\x08\x08.*)/s) { | |
123 | } elsif ($data =~ /(\x1F\x8B\x08.*)/s) { | |
124 | 124 | $self->{logger}->debug2("format: Gzip"); |
125 | 125 | return $self->_uncompressGzip($1); |
126 | 126 | } elsif ($data =~ /(<html><\/html>|)[^<]*(<.*>)\s*$/s) { |
34 | 34 | bless $self, $class; |
35 | 35 | |
36 | 36 | # create user agent |
37 | $self->{ua} = LWP::UserAgent->new(keep_alive => 1, requests_redirectable => ['POST', 'GET', 'HEAD']); | |
37 | $self->{ua} = LWP::UserAgent->new( | |
38 | parse_head => 0, # No need to parse HTML | |
39 | keep_alive => 1, | |
40 | requests_redirectable => ['POST', 'GET', 'HEAD'] | |
41 | ); | |
38 | 42 | |
39 | 43 | if ($params{proxy}) { |
40 | 44 | $self->{ua}->proxy(['http', 'https'], $params{proxy}); |
49 | 53 | } |
50 | 54 | |
51 | 55 | sub request { |
52 | my ($self, $request) = @_; | |
56 | my ($self, $request, $file) = @_; | |
53 | 57 | |
54 | 58 | my $logger = $self->{logger}; |
55 | 59 | |
62 | 66 | if ($OSNAME eq 'MSWin32' && $scheme eq 'https') { |
63 | 67 | alarm $self->{timeout}; |
64 | 68 | } |
65 | $result = $self->{ua}->request($request); | |
69 | $result = $self->{ua}->request($request, $file); | |
66 | 70 | alarm 0; |
67 | 71 | }; |
68 | 72 | |
92 | 96 | if ($OSNAME eq 'MSWin32' && $scheme eq 'https') { |
93 | 97 | alarm $self->{timeout}; |
94 | 98 | } |
95 | $result = $self->{ua}->request($request); | |
99 | $result = $self->{ua}->request($request, $file); | |
96 | 100 | alarm 0; |
97 | 101 | }; |
98 | 102 | if (!$result->is_success()) { |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | 4 | use threads; |
5 | use threads::shared; | |
5 | 6 | |
6 | 7 | use English qw(-no_match_vars); |
7 | 8 | use HTTP::Daemon; |
17 | 18 | my ($class, %params) = @_; |
18 | 19 | |
19 | 20 | my $self = { |
20 | logger => $params{logger} || | |
21 | FusionInventory::Agent::Logger->new(), | |
22 | agent => $params{agent}, | |
23 | scheduler => $params{scheduler}, | |
24 | htmldir => $params{htmldir}, | |
25 | ip => $params{ip}, | |
26 | port => $params{port} || 62354, | |
27 | trust => $params{trust} | |
28 | ||
21 | logger => $params{logger} || | |
22 | FusionInventory::Agent::Logger->new(), | |
23 | agent => $params{agent}, | |
24 | scheduler => $params{scheduler}, | |
25 | htmldir => $params{htmldir}, | |
26 | ip => $params{ip}, | |
27 | port => $params{port} || 62354, | |
28 | trust => $params{trust} | |
29 | 29 | }; |
30 | 30 | bless $self, $class; |
31 | 31 | |
32 | $SIG{PIPE} = 'IGNORE'; | |
32 | $self->{stop} = 0; | |
33 | my $stop = \$self->{stop}; | |
34 | threads::shared::share($stop); | |
33 | 35 | $self->{listener} = threads->create('_listen', $self); |
34 | 36 | |
35 | 37 | return $self; |
39 | 41 | my ($self, $client, $request, $clientIp) = @_; |
40 | 42 | |
41 | 43 | my $logger = $self->{logger}; |
42 | my $scheduler = $self->{scheduler}; | |
43 | my $htmldir = $self->{htmldir}; | |
44 | 44 | |
45 | 45 | if (!$request) { |
46 | 46 | $client->close(); |
64 | 64 | SWITCH: { |
65 | 65 | # root request |
66 | 66 | if ($path eq '/') { |
67 | ||
68 | my $template = Text::Template->new( | |
69 | TYPE => 'FILE', SOURCE => "$self->{htmldir}/index.tpl" | |
70 | ); | |
71 | if (!$template) { | |
72 | $logger->error($log_prefix . "Template access failed: $Text::Template::ERROR"); | |
73 | ; | |
74 | ||
75 | my $response = HTTP::Response->new( | |
76 | 500, | |
77 | 'KO', | |
78 | HTTP::Headers->new('Content-Type' => 'text/html'), | |
79 | "No template" | |
80 | ); | |
81 | ||
82 | $client->send_response($response); | |
83 | return; | |
84 | } | |
85 | ||
86 | my $hash = { | |
87 | version => $FusionInventory::Agent::VERSION, | |
88 | trust => $self->_is_trusted($clientIp), | |
89 | status => $self->{agent}->getStatus(), | |
90 | targets => [ | |
91 | map { $_->getStatus() } $self->{scheduler}->getTargets() | |
92 | ] | |
93 | }; | |
94 | ||
95 | my $response = HTTP::Response->new( | |
96 | 200, | |
97 | 'OK', | |
98 | HTTP::Headers->new('Content-Type' => 'text/html'), | |
99 | $template->fill_in(HASH => $hash) | |
100 | ); | |
101 | ||
102 | $client->send_response($response); | |
103 | ||
67 | $self->_handle_root($client, $request, $clientIp); | |
104 | 68 | last SWITCH; |
105 | 69 | } |
106 | 70 | |
107 | 71 | # deploy request |
108 | 72 | if ($path =~ m{^/deploy/getFile/./../([\w\d/-]+)$}) { |
109 | File::Find->require; | |
110 | my $sha512 = $1; | |
111 | my $filePath; | |
112 | foreach my $target (@{$self->{scheduler}{targets}}) { | |
113 | my $file; | |
114 | my $shareDir = $target->{storage}{directory}."/deploy/fileparts/shared"; | |
115 | next unless -d $shareDir; | |
116 | File::Find::find({ | |
117 | wanted => sub { | |
118 | return unless -f; | |
119 | return unless basename($_) eq $sha512; | |
120 | Digest::SHA->require; | |
121 | my $sha = Digest::SHA->new('512'); | |
122 | $sha->addfile($File::Find::name, 'b'); | |
123 | ||
124 | if ($sha->hexdigest eq $sha512) { | |
125 | $filePath = $File::Find::name; | |
126 | return; | |
127 | } | |
128 | }, | |
129 | no_chdir => 1 | |
130 | }, $shareDir); | |
131 | last if $filePath; | |
132 | } | |
133 | if ($filePath && -f $filePath) { | |
134 | $logger->debug($log_prefix . "file $sha512 not found"); | |
135 | $client->send_file_response("$filePath"); | |
136 | $logger->debug($log_prefix . "file $filePath sent"); | |
137 | } else { | |
138 | $client->send_error(404); | |
139 | } | |
73 | $self->_handle_deploy($client, $request, $clientIp, $1); | |
140 | 74 | last SWITCH; |
141 | 75 | } |
142 | 76 | |
143 | 77 | # now request |
144 | 78 | if ($path =~ m{^/now(?:/(\S+))?$}) { |
145 | my $token = $1; | |
146 | ||
147 | my ($code, $message, $trace); | |
148 | if ( | |
149 | $self->_is_trusted($clientIp) || | |
150 | $self->_is_authenticated($token) | |
151 | ) { | |
152 | foreach my $target ($scheduler->getTargets()) { | |
153 | $target->setNextRunDate(1); | |
154 | } | |
155 | $self->{agent}->resetToken(); | |
156 | $code = 200; | |
157 | $message = "OK"; | |
158 | $trace = "valid request, forcing execution right now"; | |
159 | } else { | |
160 | $code = 403; | |
161 | $message = "Access denied"; | |
162 | $trace = "invalid request (bad token or bad address)"; | |
163 | } | |
164 | ||
165 | my $template = Text::Template->new( | |
166 | TYPE => 'FILE', SOURCE => "$self->{htmldir}/now.tpl" | |
167 | ); | |
168 | ||
169 | my $hash = { | |
170 | message => $message | |
171 | }; | |
172 | ||
173 | my $response = HTTP::Response->new( | |
174 | $code, | |
175 | 'OK', | |
176 | HTTP::Headers->new('Content-Type' => 'text/html'), | |
177 | $template->fill_in(HASH => $hash) | |
178 | ); | |
179 | ||
180 | $client->send_response($response); | |
181 | $logger->debug($log_prefix . $trace); | |
182 | ||
79 | $self->_handle_now($client, $request, $clientIp, $1); | |
183 | 80 | last SWITCH; |
184 | 81 | } |
185 | 82 | |
186 | 83 | # status request |
187 | 84 | if ($path eq '/status') { |
188 | my $status = $self->{agent}->getStatus(); | |
189 | my $response = HTTP::Response->new( | |
190 | 200, | |
191 | 'OK', | |
192 | HTTP::Headers->new('Content-Type' => 'text/plain'), | |
193 | "status: ".$status | |
194 | ); | |
195 | $client->send_response($response); | |
85 | $self->_handle_status($client, $request, $clientIp); | |
196 | 86 | last SWITCH; |
197 | 87 | } |
198 | 88 | |
199 | 89 | # static content request |
200 | 90 | if ($path =~ m{^/(logo.png|site.css|favicon.ico)$}) { |
201 | 91 | my $file = $1; |
202 | $client->send_file_response("$htmldir/$file"); | |
92 | $client->send_file_response("$self->{htmldir}/$file"); | |
203 | 93 | last SWITCH; |
204 | 94 | } |
205 | 95 | |
208 | 98 | } |
209 | 99 | |
210 | 100 | $client->close(); |
101 | } | |
102 | ||
103 | sub _handle_root { | |
104 | my ($self, $client, $request, $clientIp) = @_; | |
105 | ||
106 | my $logger = $self->{logger}; | |
107 | ||
108 | my $template = Text::Template->new( | |
109 | TYPE => 'FILE', SOURCE => "$self->{htmldir}/index.tpl" | |
110 | ); | |
111 | if (!$template) { | |
112 | $logger->error($log_prefix . "Template access failed: $Text::Template::ERROR"); | |
113 | ; | |
114 | ||
115 | my $response = HTTP::Response->new( | |
116 | 500, | |
117 | 'KO', | |
118 | HTTP::Headers->new('Content-Type' => 'text/html'), | |
119 | "No template" | |
120 | ); | |
121 | ||
122 | $client->send_response($response); | |
123 | return; | |
124 | } | |
125 | ||
126 | my $hash = { | |
127 | version => $FusionInventory::Agent::VERSION, | |
128 | trust => $self->_is_trusted($clientIp), | |
129 | status => $self->{agent}->getStatus(), | |
130 | targets => [ | |
131 | map { $_->getStatus() } $self->{scheduler}->getTargets() | |
132 | ] | |
133 | }; | |
134 | ||
135 | my $response = HTTP::Response->new( | |
136 | 200, | |
137 | 'OK', | |
138 | HTTP::Headers->new('Content-Type' => 'text/html'), | |
139 | $template->fill_in(HASH => $hash) | |
140 | ); | |
141 | ||
142 | $client->send_response($response); | |
143 | } | |
144 | ||
145 | sub _handle_deploy { | |
146 | my ($self, $client, $request, $clientIp, $sha512) = @_; | |
147 | ||
148 | my $logger = $self->{logger}; | |
149 | ||
150 | return unless $sha512 =~ /^..(.{6})/; | |
151 | my $name = $1; | |
152 | my $path; | |
153 | ||
154 | File::Find->require(); | |
155 | Digest::SHA->require(); | |
156 | ||
157 | foreach my $target ($self->{scheduler}->getTargets()) { | |
158 | my $shareDir = $target->{storage}->getDirectory()."/deploy/fileparts/shared"; | |
159 | next unless -d $shareDir; | |
160 | ||
161 | my $wanted = sub { | |
162 | return unless -f $_; | |
163 | return unless basename($_) eq $name; | |
164 | ||
165 | my $sha = Digest::SHA->new('512'); | |
166 | $sha->addfile($File::Find::name, 'b'); | |
167 | return unless $sha->hexdigest eq $sha512; | |
168 | ||
169 | $path = $File::Find::name; | |
170 | }; | |
171 | File::Find::find({ wanted => $wanted, no_chdir => 1 }, $shareDir); | |
172 | last if $path; | |
173 | } | |
174 | if ($path) { | |
175 | $logger->debug($log_prefix . "file $sha512 found"); | |
176 | $client->send_file_response($path); | |
177 | $logger->debug($log_prefix . "file $path sent"); | |
178 | } else { | |
179 | $client->send_error(404); | |
180 | } | |
181 | } | |
182 | ||
183 | sub _handle_now { | |
184 | my ($self, $client, $request, $clientIp, $token) = @_; | |
185 | ||
186 | my $logger = $self->{logger}; | |
187 | ||
188 | my ($code, $message, $trace); | |
189 | if ( | |
190 | $self->_is_trusted($clientIp) || | |
191 | $self->_is_authenticated($token) | |
192 | ) { | |
193 | foreach my $target ($self->{scheduler}->getTargets()) { | |
194 | $target->setNextRunDate(1); | |
195 | } | |
196 | $self->{agent}->resetToken(); | |
197 | $code = 200; | |
198 | $message = "OK"; | |
199 | $trace = "valid request, forcing execution right now"; | |
200 | } else { | |
201 | $code = 403; | |
202 | $message = "Access denied"; | |
203 | $trace = "invalid request (bad token or bad address)"; | |
204 | } | |
205 | ||
206 | my $template = Text::Template->new( | |
207 | TYPE => 'FILE', SOURCE => "$self->{htmldir}/now.tpl" | |
208 | ); | |
209 | ||
210 | my $hash = { | |
211 | message => $message | |
212 | }; | |
213 | ||
214 | my $response = HTTP::Response->new( | |
215 | $code, | |
216 | 'OK', | |
217 | HTTP::Headers->new('Content-Type' => 'text/html'), | |
218 | $template->fill_in(HASH => $hash) | |
219 | ); | |
220 | ||
221 | $client->send_response($response); | |
222 | $logger->debug($log_prefix . $trace); | |
223 | } | |
224 | ||
225 | sub _handle_status { | |
226 | my ($self, $client, $request, $clientIp) = @_; | |
227 | ||
228 | my $status = $self->{agent}->getStatus(); | |
229 | my $response = HTTP::Response->new( | |
230 | 200, | |
231 | 'OK', | |
232 | HTTP::Headers->new('Content-Type' => 'text/plain'), | |
233 | "status: ".$status | |
234 | ); | |
235 | $client->send_response($response); | |
211 | 236 | } |
212 | 237 | |
213 | 238 | sub _is_trusted { |
256 | 281 | |
257 | 282 | $logger->info($log_prefix . "HTTPD service started at $url"); |
258 | 283 | |
259 | # allow the thread to be stopped | |
260 | threads->set_thread_exit_only(1); | |
261 | $SIG{'KILL'} = sub { threads->exit(); }; | |
262 | ||
263 | 284 | while (1) { |
264 | 285 | my ($client, $socket) = $daemon->accept(); |
286 | last if $self->{stop}; | |
265 | 287 | next unless $socket; |
266 | 288 | my (undef, $iaddr) = sockaddr_in($socket); |
267 | 289 | my $clientIp = inet_ntoa($iaddr); |
270 | 292 | } |
271 | 293 | } |
272 | 294 | |
295 | sub terminate { | |
296 | my ($self) = @_; | |
297 | ||
298 | lock $self->{stop}; | |
299 | $self->{stop} = 1; | |
300 | } | |
301 | ||
273 | 302 | sub DESTROY { |
274 | 303 | my ($self) = @_; |
275 | 304 | |
277 | 306 | |
278 | 307 | if ($self->{listener}->is_joinable()) { |
279 | 308 | $self->{listener}->join(); |
280 | } else { | |
281 | $self->{listener}->kill('KILL')->detach(); | |
309 | } elsif (!$self->{listener}->is_detached()) { | |
310 | $self->{listener}->detach(); | |
282 | 311 | } |
283 | 312 | } |
284 | 313 |
0 | package FusionInventory::Agent::SNMP; | |
1 | ||
2 | use strict; | |
3 | use warnings; | |
4 | ||
5 | use Encode qw(encode); | |
6 | use English qw(-no_match_vars); | |
7 | use Net::SNMP; | |
8 | ||
9 | use FusionInventory::Agent::Tools; | |
10 | use FusionInventory::Agent::Tools::Network; | |
11 | ||
12 | my @bad_oids = qw( | |
13 | .1.3.6.1.2.1.2.2.1.6 | |
14 | .1.3.6.1.2.1.4.22.1.2 | |
15 | .1.3.6.1.2.1.17.1.1.0 | |
16 | .1.3.6.1.2.1.17.4.3.1.1 | |
17 | .1.3.6.1.4.1.9.9.23.1.2.1.1.4 | |
18 | ); | |
19 | my $bad_oids_pattern = '^(' . join('|', map { quotemeta($_) } @bad_oids) . ')'; | |
20 | ||
21 | sub new { | |
22 | my ($class, %params) = @_; | |
23 | ||
24 | die "no hostname parameters" unless $params{hostname}; | |
25 | ||
26 | my $version = | |
27 | ! $params{version} ? 'snmpv1' : | |
28 | $params{version} eq '1' ? 'snmpv1' : | |
29 | $params{version} eq '2c' ? 'snmpv2c' : | |
30 | $params{version} eq '3' ? 'snmpv3' : | |
31 | undef ; | |
32 | ||
33 | die "invalid SNMP version $params{version}" unless $version; | |
34 | ||
35 | my $self = {}; | |
36 | ||
37 | my $error; | |
38 | if ($version eq 'snmpv3') { | |
39 | ($self->{session}, $error) = Net::SNMP->session( | |
40 | -timeout => 1, | |
41 | -retries => 0, | |
42 | -version => $version, | |
43 | -hostname => $params{hostname}, | |
44 | -username => $params{username}, | |
45 | -authpassword => $params{authpassword}, | |
46 | -authprotocol => $params{authprotocol}, | |
47 | -privpassword => $params{privpassword}, | |
48 | -privprotocol => $params{privprotocol}, | |
49 | ); | |
50 | } else { # snmpv2c && snmpv1 # | |
51 | ($self->{session}, $error) = Net::SNMP->session( | |
52 | -timeout => 1, | |
53 | -retries => 0, | |
54 | -version => $version, | |
55 | -hostname => $params{hostname}, | |
56 | -community => $params{community}, | |
57 | ); | |
58 | } | |
59 | ||
60 | die $error unless $self->{session}; | |
61 | ||
62 | bless $self, $class; | |
63 | ||
64 | return $self; | |
65 | } | |
66 | ||
67 | sub get { | |
68 | my ($self, $oid) = @_; | |
69 | ||
70 | return unless $oid; | |
71 | ||
72 | my $session = $self->{session}; | |
73 | ||
74 | my $response = $session->get_request( | |
75 | -varbindlist => [$oid] | |
76 | ); | |
77 | ||
78 | return unless $response; | |
79 | ||
80 | return if $response->{$oid} =~ /noSuchInstance/; | |
81 | return if $response->{$oid} =~ /noSuchObject/; | |
82 | ||
83 | my $value = $response->{$oid}; | |
84 | chomp $value; | |
85 | ||
86 | return $value; | |
87 | } | |
88 | ||
89 | sub walk { | |
90 | my ($self, $oid) = @_; | |
91 | ||
92 | return unless $oid; | |
93 | ||
94 | my $session = $self->{session}; | |
95 | ||
96 | my $response = $session->get_table( | |
97 | -baseoid => $oid | |
98 | ); | |
99 | ||
100 | return unless $response; | |
101 | ||
102 | my $values; | |
103 | ||
104 | foreach my $oid (keys %{$response}) { | |
105 | my $value = $response->{$oid}; | |
106 | chomp $value; | |
107 | $values->{$oid} = $value; | |
108 | } | |
109 | ||
110 | return $values; | |
111 | } | |
112 | ||
113 | sub getMacAddress { | |
114 | my ($self, $oid) = @_; | |
115 | ||
116 | my $value = $self->get($oid); | |
117 | return unless $value; | |
118 | ||
119 | if ($oid =~ /$bad_oids_pattern/) { | |
120 | $value = _sanitizeMacAddress($value); | |
121 | } | |
122 | ||
123 | $value = alt2canonical($value); | |
124 | ||
125 | return $value; | |
126 | } | |
127 | ||
128 | sub walkMacAddresses { | |
129 | my ($self, $oid) = @_; | |
130 | ||
131 | my $values = $self->walk($oid); | |
132 | return unless $values; | |
133 | ||
134 | if ($oid =~ /$bad_oids_pattern/) { | |
135 | foreach my $value (values %$values) { | |
136 | $value = _sanitizeMacAddress($value); | |
137 | } | |
138 | } | |
139 | ||
140 | foreach my $value (values %$values) { | |
141 | $value = alt2canonical($value); | |
142 | } | |
143 | ||
144 | return $values; | |
145 | } | |
146 | ||
147 | sub _sanitizeMacAddress { | |
148 | my ($value) = @_; | |
149 | ||
150 | if ($value !~ /^0x/) { | |
151 | # convert from binary to hexadecimal | |
152 | $value = unpack 'H*', $value; | |
153 | } else { | |
154 | # drop hex prefix | |
155 | $value =~ s/^0x//; | |
156 | } | |
157 | ||
158 | return $value; | |
159 | } | |
160 | ||
161 | ||
162 | sub getSerial { | |
163 | my ($self, $oid) = @_; | |
164 | ||
165 | my $value = $self->get($oid); | |
166 | return unless $value; | |
167 | ||
168 | $value =~ s/\n//g; | |
169 | $value =~ s/\r//g; | |
170 | $value =~ s/^\s+//; | |
171 | $value =~ s/\s+$//; | |
172 | $value =~ s/\.{2,}//g; | |
173 | ||
174 | return $value; | |
175 | } | |
176 | ||
177 | 1; | |
178 | __END__ | |
179 | ||
180 | =head1 NAME | |
181 | ||
182 | FusionInventory::Agent::SNMP - An SNMP query extension | |
183 | ||
184 | =head1 DESCRIPTION | |
185 | ||
186 | This is the object used by the agent to perform SNMP queries. | |
187 | ||
188 | =head1 METHODS | |
189 | ||
190 | =head2 new(%params) | |
191 | ||
192 | The constructor. The following parameters are allowed, as keys of the %params | |
193 | hash: | |
194 | ||
195 | =over | |
196 | ||
197 | =item version (mandatory) | |
198 | ||
199 | Can be one of: | |
200 | ||
201 | =over | |
202 | ||
203 | =item '1' | |
204 | ||
205 | =item '2c' | |
206 | ||
207 | =item '3' | |
208 | ||
209 | =back | |
210 | ||
211 | =item hostname (mandatory) | |
212 | ||
213 | =item community | |
214 | ||
215 | =item username | |
216 | ||
217 | =item authpassword | |
218 | ||
219 | =item authprotocol | |
220 | ||
221 | =item privpassword | |
222 | ||
223 | =item privprotocol | |
224 | ||
225 | =back | |
226 | ||
227 | =head2 get($oid) | |
228 | ||
229 | This method returns a single value, corresponding to a single OID. The value is | |
230 | normalised to remove any control character, and hexadecimal mac addresses are | |
231 | translated into plain ascii. | |
232 | ||
233 | =head2 walk($oid) | |
234 | ||
235 | This method returns an hashref of values, indexed by their OIDs, starting from | |
236 | the given one. The values are normalised to remove any control character, and | |
237 | hexadecimal mac addresses are translated into plain ascii. | |
238 | ||
239 | =head2 getSerial($oid) | |
240 | ||
241 | Wraps get($oid), assuming the value is a serial number and sanitizing it | |
242 | accordingly. | |
243 | ||
244 | =head2 getMacAddress($oid) | |
245 | ||
246 | Wraps get($oid), assuming the value is a mac address and sanitizing it | |
247 | accordingly. | |
248 | ||
249 | =head2 walkMacAddresses($oid) | |
250 | ||
251 | Wraps walk($oid), assuming the values are mac addresses and sanitizing them | |
252 | accordingly. |
13 | 13 | die 'no basevardir parameter' unless $params{basevardir}; |
14 | 14 | |
15 | 15 | my $self = { |
16 | logger => $params{logger} || | |
17 | FusionInventory::Agent::Logger->new(), | |
18 | maxDelay => $params{maxDelay} || 3600, | |
16 | logger => $params{logger} || | |
17 | FusionInventory::Agent::Logger->new(), | |
18 | maxDelay => $params{maxDelay} || 3600, | |
19 | initialDelay => $params{delaytime}, | |
19 | 20 | }; |
20 | 21 | bless $self, $class; |
21 | 22 | |
38 | 39 | # handle persistent state |
39 | 40 | $self->_loadState(); |
40 | 41 | |
41 | $self->{nextRunDate} = _computeNextRunDate($self->{maxDelay}) | |
42 | $self->{nextRunDate} = $self->_computeNextRunDate() | |
42 | 43 | if !$self->{nextRunDate}; |
43 | 44 | |
44 | 45 | $self->_saveState(); |
81 | 82 | my ($self) = @_; |
82 | 83 | |
83 | 84 | lock($self->{nextRunDate}) if $self->{shared}; |
84 | $self->{nextRunDate} = _computeNextRunDate($self->{maxDelay}); | |
85 | $self->{nextRunDate} = $self->_computeNextRunDate(); | |
85 | 86 | $self->_saveState(); |
86 | 87 | } |
87 | 88 | |
116 | 117 | # compute a run date, as current date and a random delay |
117 | 118 | # between maxDelay / 2 and maxDelay |
118 | 119 | sub _computeNextRunDate { |
119 | my ($maxDelay) = @_; | |
120 | ||
121 | return | |
122 | time + | |
123 | $maxDelay / 2 + | |
124 | int rand($maxDelay / 2); | |
120 | my ($self) = @_; | |
121 | ||
122 | my $ret; | |
123 | if ($self->{initialDelay}) { | |
124 | $ret = time + $self->{initialDelay}; | |
125 | $self->{initialDelay} = undef; | |
126 | } else { | |
127 | $ret = | |
128 | time + | |
129 | $self->{maxDelay} / 2 + | |
130 | int rand($self->{maxDelay} / 2); | |
131 | } | |
132 | ||
133 | return $ret; | |
125 | 134 | } |
126 | 135 | |
127 | 136 | sub _loadState { |
19 | 19 | my $logger = $params{logger}; |
20 | 20 | |
21 | 21 | my $command = 'pkg_info'; |
22 | my $packages = _getPackagesFromPkgInfo( | |
22 | my $packages = _getPackagesListFromPkgInfo( | |
23 | 23 | logger => $logger, command => $command |
24 | 24 | ); |
25 | 25 | |
40 | 40 | push @packages, { |
41 | 41 | NAME => $1, |
42 | 42 | VERSION => $2, |
43 | VERSION => $3 | |
43 | DESCRIPTION => $3 | |
44 | 44 | }; |
45 | 45 | } |
46 | 46 |
101 | 101 | |
102 | 102 | my ($vendor_id, $device_id, $class_id); |
103 | 103 | while (my $line = <$handle>) { |
104 | next if $line =~ /^#/; | |
105 | 104 | |
106 | if ($line =~ /^(\S{4}) \s+ (.*)/x) { | |
107 | # Vendor ID | |
108 | $vendor_id = $1; | |
109 | $vendors->{$vendor_id}->{name} = $2; | |
110 | } elsif ($line =~ /^\t (\S{4}) \s+ (.*)/x) { | |
105 | if ($line =~ /^\t (\S{4}) \s+ (.*)/x) { | |
111 | 106 | # Device ID |
112 | 107 | $device_id = $1; |
113 | 108 | $vendors->{$vendor_id}->{devices}->{$device_id}->{name} = $2; |
115 | 110 | # Subdevice ID |
116 | 111 | my $subdevice_id = "$1:$2"; |
117 | 112 | $vendors->{$vendor_id}->{devices}->{$device_id}->{subdevices}->{$subdevice_id}->{name} = $3; |
113 | } elsif ($line =~ /^(\S{4}) \s+ (.*)/x) { | |
114 | # Vendor ID | |
115 | $vendor_id = $1; | |
116 | $vendors->{$vendor_id}->{name} = $2; | |
118 | 117 | } elsif ($line =~ /^C \s+ (\S{2}) \s+ (.*)/x) { |
119 | 118 | # Class ID |
120 | 119 | $class_id = $1; |
20 | 20 | pattern => qr/Description:\s+(.+)/ |
21 | 21 | ); |
22 | 22 | |
23 | # See: #1262 | |
24 | $release =~ s/^Enterprise Linux Enterprise Linux/Oracle Linux/; | |
25 | ||
23 | 26 | my $linuxDistributionName; |
24 | 27 | my $linuxDistributionVersion; |
25 | 28 | # Redirect stderr to /dev/null to avoid "No LSB modules are available" message |
5 | 5 | use FusionInventory::Agent::Tools; |
6 | 6 | use FusionInventory::Agent::Tools::Network; |
7 | 7 | use FusionInventory::Agent::Tools::Unix; |
8 | use FusionInventory::Agent::Tools::Linux; | |
8 | 9 | |
9 | 10 | sub isEnabled { |
10 | 11 | return |
49 | 50 | my $routes = $params{routes}; |
50 | 51 | |
51 | 52 | my @interfaces = canRun("/sbin/ip") ? |
52 | _parseIpAddrShow(command => '/sbin/ip addr show', logger => $logger): | |
53 | _parseIfconfig(command => '/sbin/ifconfig -a', logger => $logger); | |
53 | getInterfacesFromIp(logger => $logger): | |
54 | getInterfacesFromIfconfig(logger => $logger); | |
54 | 55 | |
55 | 56 | foreach my $interface (@interfaces) { |
56 | 57 | if (_isWifi($logger, $interface->{DESCRIPTION})) { |
91 | 92 | } |
92 | 93 | } |
93 | 94 | } |
94 | ||
95 | return @interfaces; | |
96 | } | |
97 | ||
98 | sub _parseIfconfig { | |
99 | my $handle = getFileHandle(@_); | |
100 | return unless $handle; | |
101 | ||
102 | my @interfaces; | |
103 | my $interface; | |
104 | ||
105 | while (my $line = <$handle>) { | |
106 | if ($line =~ /^$/) { | |
107 | # end of interface section | |
108 | push @interfaces, $interface if $interface; | |
109 | next; | |
110 | } | |
111 | ||
112 | if ($line =~ /^(\S+)/) { | |
113 | # new interface | |
114 | $interface = { | |
115 | STATUS => 'Down', | |
116 | DESCRIPTION => $1 | |
117 | } | |
118 | } | |
119 | if ($line =~ /inet addr:($ip_address_pattern)/i) { | |
120 | $interface->{IPADDRESS} = $1; | |
121 | } | |
122 | if ($line =~ /Mask:($ip_address_pattern)/) { | |
123 | $interface->{IPMASK} = $1; | |
124 | } | |
125 | if ($line =~ /inet6 addr: (\S+)/i) { | |
126 | $interface->{IPADDRESS6} = $1; | |
127 | } | |
128 | if ($line =~ /hwadd?r\s+($mac_address_pattern)/i) { | |
129 | $interface->{MACADDR} = $1; | |
130 | } | |
131 | if ($line =~ /^\s+UP\s/) { | |
132 | $interface->{STATUS} = 'Up'; | |
133 | } | |
134 | if ($line =~ /link encap:(\S+)/i) { | |
135 | $interface->{TYPE} = $1; | |
136 | } | |
137 | ||
138 | } | |
139 | close $handle; | |
140 | 95 | |
141 | 96 | return @interfaces; |
142 | 97 | } |
212 | 167 | return ($driver, $pcislot); |
213 | 168 | } |
214 | 169 | |
215 | ||
216 | # http://forge.fusioninventory.org/issues/854 | |
217 | sub _parseIpAddrShow { | |
218 | my $handle = getFileHandle(@_); | |
219 | return unless $handle; | |
220 | ||
221 | my @entries; | |
222 | my $entry; | |
223 | while (my $line = <$handle>) { | |
224 | chomp $line; | |
225 | if ($line =~ /^\d+:\s+(\S+): .*(UP|DOWN)/) { | |
226 | push @entries, $entry if $entry; | |
227 | $entry = {}; | |
228 | $entry->{DESCRIPTION} = $1; | |
229 | $entry->{STATUS} = ucfirst(lc($2)); | |
230 | } elsif ($line =~ /link\/ether ($mac_address_pattern)/) { | |
231 | $entry->{MACADDR} = $1; | |
232 | } elsif ($line =~ /inet6 (\S+)\//) { | |
233 | $entry->{IPADDRESS6} = $1; | |
234 | } elsif ($line =~ /inet ($ip_address_pattern)\/(\d{1,3})/) { | |
235 | $entry->{IPADDRESS} = $1; | |
236 | $entry->{IPMASK} = getNetworkMask($1, $2); | |
237 | $entry->{IPSUBNET} = getSubnetAddress( | |
238 | $entry->{IPADDRESS}, $entry->{IPMASK} | |
239 | ); | |
240 | } | |
241 | } | |
242 | ||
243 | return @entries; | |
244 | } | |
245 | ||
246 | 170 | 1; |
6 | 6 | |
7 | 7 | use FusionInventory::Agent::Tools; |
8 | 8 | use FusionInventory::Agent::Tools::Network; |
9 | use FusionInventory::Agent::Tools::Unix; | |
9 | 10 | |
10 | 11 | sub isEnabled { |
11 | 12 | return canRun('ifconfig'); |
4 | 4 | |
5 | 5 | use FusionInventory::Agent::Tools; |
6 | 6 | use FusionInventory::Agent::Tools::MacOS; |
7 | ||
7 | 8 | sub isEnabled { |
8 | 9 | return |
9 | 10 | -r '/usr/sbin/system_profiler' |
10 | 11 | } |
11 | 12 | |
13 | sub doInventory { | |
14 | my (%params) = @_; | |
15 | ||
16 | my $inventory = $params{inventory}; | |
17 | ||
18 | my %displays = _getDisplays(); | |
19 | foreach my $section (keys %displays ) { | |
20 | foreach my $entry (@{$displays{$section}}) { | |
21 | $inventory->addEntry( | |
22 | section => $section, | |
23 | entry => $entry, | |
24 | ); | |
25 | } | |
26 | } | |
27 | } | |
12 | 28 | |
13 | 29 | sub _getDisplays { |
14 | 30 | my $infos = getSystemProfilerInfos(@_); |
21 | 37 | |
22 | 38 | my $displays = {}; |
23 | 39 | foreach my $displayName (keys %{$videoCardInfo->{Displays}}) { |
24 | next if $displayName =~ /^Display Connector$/; | |
25 | next if $displayName =~ /^Display$/; | |
40 | next if $displayName eq 'Display Connector'; | |
41 | next if $displayName eq 'Display'; | |
26 | 42 | my $displayInfo = $videoCardInfo->{Displays}{$displayName}; |
27 | ||
28 | 43 | |
29 | 44 | my $resolution = $displayInfo->{Resolution}; |
30 | 45 | if ($resolution) { |
35 | 50 | my $memory = $videoCardInfo->{'VRAM (Total)'}; |
36 | 51 | $memory =~ s/\ .*//g if $memory; |
37 | 52 | |
38 | ||
39 | ||
40 | # use Data::Dumper; | |
41 | # print "display-BEGIN-\n"; | |
42 | # print Dumper($displayInfo); | |
43 | # print "display-END-\n"; | |
44 | # print "video-BEGIN-\n"; | |
45 | # print Dumper($videoCardInfo); | |
46 | # print "video-END-\n"; | |
47 | ||
48 | ||
49 | ||
50 | 53 | push @$videos, { |
51 | CHIPSET => $videoCardInfo->{'Chipset Model'}, | |
52 | MEMORY => $memory, | |
53 | NAME => $videoName, | |
54 | CHIPSET => $videoCardInfo->{'Chipset Model'}, | |
55 | MEMORY => $memory, | |
56 | NAME => $videoName, | |
54 | 57 | RESOLUTION => $resolution, |
55 | PCISLOT => $videoCardInfo->{Slot} | |
58 | PCISLOT => $videoCardInfo->{Slot} | |
56 | 59 | }; |
57 | 60 | |
58 | 61 | push @$monitors, { |
59 | CAPTION => $displayName, | |
62 | CAPTION => $displayName, | |
60 | 63 | DESCRIPTION => $displayName, |
61 | MANUFACTURER => '', | |
62 | SERIAL => '', | |
63 | 64 | } |
64 | 65 | } |
65 | 66 | } |
66 | 67 | |
67 | 68 | return ( |
68 | 69 | MONITORS => $monitors, |
69 | VIDEOS => $videos | |
70 | VIDEOS => $videos | |
70 | 71 | ); |
71 | 72 | |
72 | 73 | } |
73 | 74 | |
74 | sub doInventory { | |
75 | my (%params) = @_; | |
76 | ||
77 | my $inventory = $params{inventory}; | |
78 | ||
79 | my %displays = _getDisplays(); | |
80 | foreach my $section (keys %displays ) { | |
81 | foreach (@{$displays{$section}}) { | |
82 | $inventory->addEntry( | |
83 | section => $section, | |
84 | entry => $_, | |
85 | ); | |
86 | } | |
87 | } | |
88 | } | |
89 | 75 | |
90 | 76 | 1; |
18 | 18 | my $class = getClass(); |
19 | 19 | |
20 | 20 | my ($count, $cpu) = |
21 | $class == 7 ? _getCPUFromPrtcl(logger => $logger) : | |
22 | _getCPUFromMemconf(logger => $logger); | |
21 | $class == SOLARIS_CONTAINER ? | |
22 | _getCPUFromPrtcl(logger => $logger) : | |
23 | _getCPUFromMemconf(logger => $logger); | |
23 | 24 | |
24 | 25 | # fallback on generic method |
25 | 26 | if (!$count) { |
14 | 14 | command => "df --version" |
15 | 15 | ); |
16 | 16 | |
17 | return $line =~ /GNU/ ? | |
17 | # df --help is on STDERR on some system | |
18 | # so $line is undef | |
19 | return ($line && $line =~ /GNU/) ? | |
18 | 20 | "df -P -k" : |
19 | 21 | "df -k"; |
20 | 22 | } |
48 | 50 | command => "zfs get org.opensolaris.libbe:uuid $filesystem->{VOLUMN}" |
49 | 51 | ); |
50 | 52 | |
51 | if ($line =~ /org.opensolaris.libbe:uuid\s+(\S{5}\S+)/) { | |
53 | if ($line && $line =~ /org.opensolaris.libbe:uuid\s+(\S{5}\S+)/) { | |
52 | 54 | $filesystem->{UUID} = $1; |
53 | 55 | $filesystem->{FILESYSTEM} = 'zfs'; |
54 | 56 | next; |
23 | 23 | } |
24 | 24 | |
25 | 25 | my @memories = |
26 | $class == 1 ? _getMemories1() : | |
27 | $class == 2 ? _getMemories2() : | |
28 | $class == 3 ? _getMemories3() : | |
29 | $class == 4 ? _getMemories4() : | |
30 | $class == 5 ? _getMemories5() : | |
31 | $class == 6 ? _getMemories6() : | |
32 | $class == 7 ? _getMemories7() : | |
33 | () ; | |
26 | $class == SOLARIS_FIRE ? _getMemories1() : | |
27 | $class == SOLARIS_FIRE_V ? _getMemories2() : | |
28 | $class == SOLARIS_FIRE_T ? _getMemories3() : | |
29 | $class == SOLARIS_ENTERPRISE_T ? _getMemories4() : | |
30 | $class == SOLARIS_ENTERPRISE ? _getMemories5() : | |
31 | $class == SOLARIS_I86PC ? _getMemories6() : | |
32 | $class == SOLARIS_CONTAINER ? _getMemories7() : | |
33 | () ; | |
34 | 34 | |
35 | 35 | foreach my $memory (@memories) { |
36 | 36 | $inventory->addEntry( |
18 | 18 | my $class = getClass(); |
19 | 19 | |
20 | 20 | my @slots = |
21 | $class == 4 ? _getSlots4(logger => $logger, command => 'prtdiag') : | |
22 | $class == 5 ? _getSlots5(logger => $logger, command => 'prtdiag') : | |
23 | _getSlotsDefault(logger => $logger, command => 'prtdiag') ; | |
21 | $class == SOLARIS_ENTERPRISE_T ? _getSlots4(logger => $logger) : | |
22 | $class == SOLARIS_ENTERPRISE ? _getSlots5(logger => $logger) : | |
23 | _getSlotsDefault(logger => $logger) ; | |
24 | 24 | |
25 | 25 | foreach my $slot (@slots) { |
26 | 26 | $inventory->addEntry( |
31 | 31 | } |
32 | 32 | |
33 | 33 | sub _getSlots4 { |
34 | my %params = ( | |
35 | command => 'prtdiag', | |
36 | @_ | |
37 | ); | |
34 | 38 | |
35 | my $handle = getFileHandle(@_); | |
39 | my $handle = getFileHandle(%params); | |
36 | 40 | return unless $handle; |
37 | 41 | |
38 | 42 | my @slots; |
52 | 56 | } |
53 | 57 | |
54 | 58 | sub _getSlots5 { |
59 | my %params = ( | |
60 | command => 'prtdiag', | |
61 | @_ | |
62 | ); | |
55 | 63 | |
56 | my $handle = getFileHandle(@_); | |
64 | my $handle = getFileHandle(%params); | |
57 | 65 | return unless $handle; |
58 | 66 | |
59 | 67 | my @slots; |
98 | 106 | } |
99 | 107 | |
100 | 108 | sub _getSlotsDefault { |
109 | my %params = ( | |
110 | command => 'prtdiag', | |
111 | @_ | |
112 | ); | |
101 | 113 | |
102 | my $handle = getFileHandle(@_); | |
114 | my $handle = getFileHandle(%params); | |
103 | 115 | return unless $handle; |
104 | 116 | |
105 | 117 | my @slots; |
7 | 7 | use FusionInventory::Agent::Tools::Unix; |
8 | 8 | |
9 | 9 | sub isEnabled { |
10 | # Avoid duplicated entry with libvirt | |
11 | return if can_run('virsh'); | |
12 | ||
10 | 13 | return |
11 | 14 | canRun('qemu') || |
12 | 15 | canRun('kvm') || |
3 | 3 | use warnings; |
4 | 4 | |
5 | 5 | use English qw(-no_match_vars); |
6 | use File::Basename; | |
7 | use File::Glob qw(:glob); | |
6 | use User::pwent; | |
8 | 7 | |
9 | 8 | use FusionInventory::Agent::Tools; |
10 | 9 | |
26 | 25 | my $logger = $params{logger}; |
27 | 26 | my $scanhomedirs = $params{scan_homedirs}; |
28 | 27 | |
29 | my $cmd_list_vms = "VBoxManage -nologo list --long vms"; | |
28 | my $command = "VBoxManage -nologo list --long vms"; | |
30 | 29 | |
31 | my $owner; | |
32 | if ( $REAL_USER_ID != 0 ) { | |
33 | $owner = getpwuid $REAL_USER_ID; | |
34 | } | |
30 | my $owner = getpwuid($REAL_USER_ID)->name(); | |
35 | 31 | |
36 | foreach my $machine (_parseVBoxManage(logger => $logger, command => $cmd_list_vms)) { | |
32 | foreach my $machine (_parseVBoxManage( | |
33 | logger => $logger, command => $command | |
34 | )) { | |
37 | 35 | $machine->{OWNER} = $owner; |
38 | 36 | $inventory->addEntry( |
39 | 37 | section => 'VIRTUALMACHINES', entry => $machine |
40 | 38 | ); |
41 | 39 | } |
42 | 40 | |
41 | return unless $scanhomedirs == 1 && $REAL_USER_ID == 0; | |
43 | 42 | |
44 | # If home directories scan is authorized | |
45 | if ($scanhomedirs == 1 && $REAL_USER_ID == 0) { | |
46 | my $homeDir = "/home"; | |
43 | # assume all system users with a suitable homedir is an actual human user | |
44 | my $pattern = $OSNAME eq 'darwin' ? | |
45 | qr{^/Users} : qr{^/home}; | |
47 | 46 | |
48 | if ($OSNAME eq 'darwin') { | |
49 | $homeDir = "/Users"; | |
50 | } | |
51 | my @homeDirlist = glob("$homeDir/*"); | |
52 | return if @homeDirlist > 10; # To many users, ignored. | |
53 | foreach (@homeDirlist) { | |
54 | my $login = basename($_); | |
55 | next unless getpwnam ($login); # Invalid account | |
56 | my $cmd_list_vms = "su \"$login\" -c \"VBoxManage -nologo list --long vms\""; | |
57 | foreach my $machine (_parseVBoxManage(logger => $logger, command => $cmd_list_vms)) { | |
58 | $machine->{OWNER} = $login; | |
59 | $inventory->addEntry( | |
60 | section => 'VIRTUALMACHINES', entry => $machine | |
61 | ); | |
62 | } | |
47 | my @users; | |
48 | while (my $user = getpwent()) { | |
49 | next unless $user->dir() =~ /$pattern/; | |
50 | push @users, $user->name(); | |
51 | } | |
63 | 52 | |
53 | # abort if too many users | |
54 | return if @users > 10; | |
55 | ||
56 | foreach my $user (@users) { | |
57 | my $command = "su '$user' -c 'VBoxManage -nologo list --long vms'"; | |
58 | foreach my $machine (_parseVBoxManage( | |
59 | logger => $logger, command => $command | |
60 | )) { | |
61 | $machine->{OWNER} = $user; | |
62 | $inventory->addEntry( | |
63 | section => 'VIRTUALMACHINES', entry => $machine | |
64 | ); | |
64 | 65 | } |
65 | 66 | } |
66 | 67 | } |
76 | 77 | chomp $line; |
77 | 78 | |
78 | 79 | if ($line =~ m/^Name:\s+(.*)$/) { |
79 | # this is a little tricky, because USB devices also have a 'name' | |
80 | # field, so let's use the 'index' field to disambiguate | |
80 | # this is a little tricky, because USB devices also have a 'name' | |
81 | # field, so let's use the 'index' field to disambiguate | |
81 | 82 | if (defined $index) { |
82 | 83 | $index = undef; |
83 | 84 | next; |
84 | 85 | } |
85 | if ($machine) { | |
86 | $machine->{VCPU} = 1; | |
87 | $machine->{SUBSYSTEM} = 'Oracle VM VirtualBox'; | |
88 | $machine->{VMTYPE} = 'VirtualBox'; | |
89 | push @machines, $machine; | |
90 | } | |
86 | push @machines, $machine if $machine; | |
91 | 87 | $machine = { |
92 | NAME => $1 | |
93 | } | |
88 | NAME => $1, | |
89 | VCPU => 1, | |
90 | SUBSYSTEM => 'Oracle VM VirtualBox', | |
91 | VMTYPE => 'VirtualBox' | |
92 | }; | |
94 | 93 | } elsif ($line =~ m/^UUID:\s+(.+)/) { |
95 | 94 | $machine->{UUID} = $1; |
96 | 95 | } elsif ($line =~ m/^Memory size:\s+(.+)/ ) { |
103 | 102 | } |
104 | 103 | close $handle; |
105 | 104 | |
106 | # push last remaining machine | |
107 | if ($machine) { | |
108 | $machine->{VCPU} = 1; | |
109 | $machine->{SUBSYSTEM} = 'Oracle VM VirtualBox'; | |
110 | $machine->{VMTYPE} = 'VirtualBox'; | |
111 | push @machines, $machine; | |
112 | } | |
105 | # push last remaining machine | |
106 | push @machines, $machine if $machine; | |
113 | 107 | |
114 | 108 | return @machines; |
115 | 109 | } |
47 | 47 | |
48 | 48 | use FusionInventory::Agent::Tools; |
49 | 49 | use FusionInventory::Agent::Tools::Solaris; |
50 | ||
51 | my @vmware_patterns = ( | |
52 | 'VMware vmxnet virtual NIC driver', | |
53 | 'Vendor: VMware\s+Model: Virtual disk', | |
54 | 'Vendor: VMware,\s+Model: VMware Virtual ', | |
55 | ': VMware Virtual IDE CDROM Drive' | |
56 | ); | |
57 | my $vmware_pattern = _assemblePatterns(@vmware_patterns); | |
58 | ||
59 | my @qemu_patterns = ( | |
60 | ' QEMUAPIC ', | |
61 | 'QEMU Virtual CPU', | |
62 | ': QEMU HARDDISK,', | |
63 | ': QEMU CD-ROM,' | |
64 | ); | |
65 | my $qemu_pattern = _assemblePatterns(@qemu_patterns); | |
66 | ||
67 | my @virtual_machine_patterns = ( | |
68 | ': Virtual HD,', | |
69 | ': Virtual CD,' | |
70 | ); | |
71 | my $virtual_machine_pattern = _assemblePatterns(@virtual_machine_patterns); | |
72 | ||
73 | my @virtualbox_patterns = ( | |
74 | ' VBOXBIOS ', | |
75 | ': VBOX HARDDISK,', | |
76 | ': VBOX CD-ROM,', | |
77 | ); | |
78 | my $virtualbox_pattern = _assemblePatterns(@virtualbox_patterns); | |
79 | ||
80 | my @xen_patterns = ( | |
81 | 'Hypervisor signature: xen', | |
82 | 'Xen virtual console successfully installed', | |
83 | 'Xen reported:', | |
84 | 'Xen: \d+ - \d+', | |
85 | 'xen-vbd: registered block device', | |
86 | 'ACPI: [A-Z]{4} \(v\d+\s+Xen ', | |
87 | ); | |
88 | my $xen_pattern = _assemblePatterns(@xen_patterns); | |
89 | ||
90 | my %module_patterns = ( | |
91 | '^vmxnet\s' => 'VMware', | |
92 | '^xen_\w+front\s' => 'Xen', | |
93 | ); | |
50 | 94 | |
51 | 95 | sub isEnabled { |
52 | 96 | return 1; |
109 | 153 | } |
110 | 154 | } |
111 | 155 | |
112 | # Parse loaded modules | |
113 | my %modmap = ( | |
114 | '^vmxnet\s' => 'VMware', | |
115 | '^xen_\w+front\s' => 'Xen', | |
116 | ); | |
156 | my $result; | |
157 | ||
158 | # loaded modules | |
117 | 159 | |
118 | 160 | if (-f '/proc/modules') { |
119 | 161 | my $handle = getFileHandle( |
120 | 162 | file => '/proc/modules', |
121 | 163 | logger => $logger |
122 | 164 | ); |
123 | while (<$handle>) { | |
124 | foreach my $str (keys %modmap) { | |
125 | next unless /$str/; | |
126 | close $handle; | |
127 | return $modmap{$str}; | |
165 | while (my $line = <$handle>) { | |
166 | foreach my $pattern (keys %module_patterns) { | |
167 | next unless $line =~ /$pattern/; | |
168 | $result = $module_patterns{$pattern}; | |
169 | last; | |
128 | 170 | } |
129 | 171 | } |
130 | 172 | close $handle; |
131 | 173 | } |
132 | ||
133 | # Let's parse some logs & /proc files for well known strings | |
134 | my %msgmap = ( | |
135 | 'VMware vmxnet virtual NIC driver' => 'VMware', | |
136 | 'Vendor: VMware\s+Model: Virtual disk' => 'VMware', | |
137 | 'Vendor: VMware,\s+Model: VMware Virtual ' => 'VMware', | |
138 | ': VMware Virtual IDE CDROM Drive' => 'VMware', | |
139 | ||
140 | ' QEMUAPIC ' => 'QEMU', | |
141 | 'QEMU Virtual CPU' => 'QEMU', | |
142 | ': QEMU HARDDISK,' => 'QEMU', | |
143 | ': QEMU CD-ROM,' => 'QEMU', | |
144 | ||
145 | ': Virtual HD,' => 'Virtual Machine', | |
146 | ': Virtual CD,' => 'Virtual Machine', | |
147 | ||
148 | ' VBOXBIOS ' => 'VirtualBox', | |
149 | ': VBOX HARDDISK,' => 'VirtualBox', | |
150 | ': VBOX CD-ROM,' => 'VirtualBox', | |
151 | ||
152 | 'Hypervisor signature: xen' => 'Xen', | |
153 | 'Xen virtual console successfully installed' => 'Xen', | |
154 | 'Xen reported:' => 'Xen', | |
155 | 'Xen: \d+ - \d+' => 'Xen', | |
156 | 'xen-vbd: registered block device' => 'Xen', | |
157 | 'ACPI: [A-Z]{4} \(v\d+\s+Xen ' => 'Xen', | |
158 | ); | |
174 | return $result if $result; | |
175 | ||
176 | # dmesg | |
159 | 177 | |
160 | 178 | if (-r '/var/log/dmesg') { |
161 | my $handle = getFileHandle( | |
162 | file => '/var/log/dmesg', | |
163 | logger => $logger | |
164 | ); | |
165 | while (<$handle>) { | |
166 | foreach my $str (keys %msgmap) { | |
167 | next unless /$str/; | |
168 | close $handle; | |
169 | return $msgmap{$str}; | |
170 | } | |
171 | } | |
172 | close $handle; | |
173 | } | |
174 | ||
175 | # On OpenBSD, dmesg is in sbin | |
176 | # http://forge.fusioninventory.org/issues/402 | |
177 | # TODO: we should remove the head call here | |
178 | foreach my $dmesg (qw(/bin/dmesg /sbin/dmesg)) { | |
179 | next unless -f $dmesg; | |
180 | my $command = "$dmesg | head -n 750"; | |
181 | ||
182 | my $handle = getFileHandle( | |
183 | command => $command, | |
184 | logger => $logger, | |
185 | ); | |
186 | while (<$handle>) { | |
187 | foreach my $str (keys %msgmap) { | |
188 | next unless /$str/; | |
189 | close $handle; | |
190 | return $msgmap{$str}; | |
191 | } | |
192 | } | |
193 | close $handle; | |
194 | } | |
179 | my $handle = getFileHandle(file => '/var/log/dmesg', logger => $logger); | |
180 | $result = _matchPatterns($handle); | |
181 | close $handle; | |
182 | } elsif (-x '/bin/dmesg') { | |
183 | my $handle = getFileHandle(command => '/bin/dmesg', logger => $logger); | |
184 | $result = _matchPatterns($handle); | |
185 | close $handle; | |
186 | } elsif (-x '/sbin/dmesg') { | |
187 | # On OpenBSD, dmesg is in sbin | |
188 | # http://forge.fusioninventory.org/issues/402 | |
189 | my $handle = getFileHandle(command => '/sbin/dmesg', logger => $logger); | |
190 | $result = _matchPatterns($handle); | |
191 | close $handle; | |
192 | } | |
193 | return $result if $result; | |
194 | ||
195 | # scsci | |
195 | 196 | |
196 | 197 | if (-f '/proc/scsi/scsi') { |
197 | 198 | my $handle = getFileHandle( |
198 | 199 | file => '/proc/scsi/scsi', |
199 | 200 | logger => $logger |
200 | 201 | ); |
201 | while (<$handle>) { | |
202 | foreach my $str (keys %msgmap) { | |
203 | next unless /$str/; | |
204 | close $handle; | |
205 | return $msgmap{$str}; | |
206 | } | |
207 | } | |
208 | close $handle; | |
209 | } | |
202 | $result = _findPattern($handle); | |
203 | close $handle; | |
204 | } | |
205 | return $result if $result; | |
210 | 206 | |
211 | 207 | return 'Physical'; |
212 | 208 | } |
213 | 209 | |
210 | sub _assemblePatterns { | |
211 | my (@patterns) = @_; | |
212 | ||
213 | my $pattern = '(?:' . join('|', @patterns) . ')'; | |
214 | return qr/$pattern/; | |
215 | } | |
216 | ||
217 | sub _matchPatterns { | |
218 | my ($handle) = @_; | |
219 | ||
220 | while (my $line = <$handle>) { | |
221 | return 'VMware' if $line =~ $vmware_pattern; | |
222 | return 'QEMU' if $line =~ $qemu_pattern; | |
223 | return 'Virtual Machine' if $line =~ $virtual_machine_pattern; | |
224 | return 'VirtualBox' if $line =~ $virtualbox_pattern; | |
225 | return 'Xen' if $line =~ $xen_pattern; | |
226 | } | |
227 | } | |
228 | ||
214 | 229 | 1; |
27 | 27 | |
28 | 28 | my $bios = { |
29 | 29 | BDATE => getRegistryValue( |
30 | path => "Hardware/Description/System/BIOS/BIOSReleaseDate", | |
30 | path => "HKEY_LOCAL_MACHINE/Hardware/Description/System/BIOS/BIOSReleaseDate", | |
31 | 31 | logger => $logger |
32 | 32 | ) |
33 | 33 | }; |
83 | 83 | |
84 | 84 | $inventory->setBios($bios); |
85 | 85 | |
86 | if ($bios->{VERSION} eq 'VirtualBox' || $bios->{MMODEL} eq 'VirtualBox') { | |
86 | if ( | |
87 | ($bios->{VERSION} && ($bios->{VERSION} eq 'VirtualBox')) | |
88 | || | |
89 | ($bios->{MMODEL} && ($bios->{MMODEL} eq 'VirtualBox')) | |
90 | ) { | |
87 | 91 | $inventory->setHardware ({ |
88 | 92 | VMSYSTEM => 'VirtualBox' |
89 | 93 | }); |
82 | 82 | |
83 | 83 | $nics = $WMIService->ExecQuery('SELECT * FROM Win32_NetworkAdapter'); |
84 | 84 | foreach my $nic (in $nics) { |
85 | my $interface = {}; | |
86 | 85 | # http://comments.gmane.org/gmane.comp.monitoring.fusion-inventory.devel/34 |
87 | 86 | next unless $nic->PNPDeviceID; |
88 | 87 | |
89 | my $virtualdev = 0; | |
88 | my $interface = { | |
89 | SPEED => $nic->Speed, | |
90 | MACADDR => $nic->MACAddress, | |
91 | PNPDEVICEID => $nic->PNPDeviceID, | |
92 | }; | |
93 | ||
90 | 94 | # PhysicalAdapter only work on OS > XP |
91 | if (!defined($nic->PhysicalAdapter)) { | |
92 | if ($nic->PNPDeviceID =~ /^ROOT/) { | |
93 | $virtualdev = 1; | |
94 | } | |
95 | if (defined $nic->PhysicalAdapter) { | |
96 | $interface->{VIRTUALDEV} = $nic->PhysicalAdapter ? 0 : 1; | |
97 | # http://forge.fusioninventory.org/issues/1166 | |
98 | } elsif ($interface->{description} =~ /RAS Async Adapter/i) { | |
99 | $interface->{VIRTUALDEV} = 1; | |
95 | 100 | } else { |
96 | $virtualdev = $nic->PhysicalAdapter ? 0 : 1; | |
101 | $interface->{VIRTUALDEV} = $nic->PNPDeviceID =~ /^ROOT/ ? 1 : 0; | |
97 | 102 | } |
98 | 103 | |
99 | $interface->{SPEED} = $nic->Speed; | |
100 | $interface->{VIRTUALDEV} = $virtualdev; | |
101 | $interface->{MACADDR} = $nic->MACAddress; | |
102 | $interface->{PNPDEVICEID} = $nic->PNPDeviceID; | |
103 | 104 | push @interfaces, $interface; |
104 | 105 | } |
105 | 106 |
23 | 23 | sub isEnabled { |
24 | 24 | my (%params) = @_; |
25 | 25 | |
26 | my $prologresp = $params{prologresp}; | |
27 | ||
28 | return | |
29 | $prologresp && | |
30 | $prologresp->getOptionsInfoByName("REGISTRY"); | |
26 | return $params{registry}; | |
31 | 27 | } |
32 | 28 | |
33 | 29 | sub doInventory { |
34 | 30 | my (%params) = @_; |
35 | 31 | |
36 | 32 | my $inventory = $params{inventory}; |
37 | my $prologresp = $params{prologresp}; | |
38 | 33 | |
39 | my $options = $prologresp->getOptionsInfoByName("REGISTRY"); | |
40 | ||
41 | foreach my $option (@$options) { | |
34 | foreach my $option (@{$params{registry}}) { | |
42 | 35 | my $name = $option->{NAME}; |
43 | 36 | my $regkey = $option->{REGKEY}; |
44 | 37 | my $regtree = $option->{REGTREE}; |
11 | 11 | qw/KEY_READ/ |
12 | 12 | ); |
13 | 13 | |
14 | use FusionInventory::Agent::Tools; | |
14 | 15 | use FusionInventory::Agent::Tools::Win32; |
15 | 16 | |
16 | 17 | my $seen; |
40 | 41 | my $softwares64 = |
41 | 42 | $machKey64->{"SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall"}; |
42 | 43 | |
43 | _processSoftwares({ | |
44 | inventory => $inventory, | |
44 | foreach my $software (_getSoftwares( | |
45 | 45 | softwares => $softwares64, |
46 | 46 | is64bit => 1 |
47 | }); | |
47 | )) { | |
48 | $inventory->addEntry(section => 'SOFTWARES', entry => $software); | |
49 | } | |
48 | 50 | |
49 | 51 | my $machKey32 = $Registry->Open('LMachine', { |
50 | 52 | Access => KEY_READ | KEY_WOW64_32 ## no critic (ProhibitBitwise) |
53 | 55 | my $softwares32 = |
54 | 56 | $machKey32->{"SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall"}; |
55 | 57 | |
56 | _processSoftwares({ | |
57 | inventory => $inventory, | |
58 | foreach my $software (_getSoftwares( | |
58 | 59 | softwares => $softwares32, |
59 | is64bit => 0 | |
60 | }); | |
60 | is64bit => 0 | |
61 | )) { | |
62 | $inventory->addEntry(section => 'SOFTWARES', entry => $software); | |
63 | } | |
61 | 64 | } else { |
62 | 65 | my $machKey = $Registry->Open('LMachine', { |
63 | 66 | Access => KEY_READ |
66 | 69 | my $softwares = |
67 | 70 | $machKey->{"SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall"}; |
68 | 71 | |
69 | _processSoftwares({ | |
70 | inventory => $inventory, | |
72 | foreach my $software (_getSoftwares( | |
71 | 73 | softwares => $softwares, |
72 | is64bit => 0 | |
73 | }); | |
74 | ||
74 | is64bit => 0 | |
75 | )) { | |
76 | $inventory->addEntry(section => 'SOFTWARES', entry => $software); | |
77 | } | |
75 | 78 | } |
76 | ||
77 | 79 | } |
78 | 80 | |
79 | 81 | sub _dateFormat { |
80 | 82 | my ($date) = @_; |
81 | 83 | |
82 | return unless $date; | |
84 | ## no critic (ExplicitReturnUndef) | |
85 | return undef unless $date; | |
83 | 86 | |
84 | 87 | return unless $date =~ /^(\d{4})(\d{2})(\d{2})/; |
85 | 88 | |
86 | 89 | return "$3/$2/$1"; |
87 | 90 | } |
88 | 91 | |
89 | sub _processSoftwares { | |
90 | my ($params) = @_; | |
92 | sub _getSoftwares { | |
93 | my (%params) = @_; | |
91 | 94 | |
92 | my $softwares = $params->{softwares}; | |
93 | my $inventory = $params->{inventory}; | |
94 | my $is64bit = $params->{is64bit}; | |
95 | my $softwares = $params{softwares}; | |
96 | my $is64bit = $params{is64bit}; | |
97 | ||
98 | my @softwares; | |
95 | 99 | |
96 | 100 | foreach my $rawGuid (keys %$softwares) { |
97 | 101 | my $data = $softwares->{$rawGuid}; |
98 | next unless keys %$data; | |
99 | ||
100 | my $guid = $rawGuid; | |
101 | $guid =~ s/\/$//; # drop the tailing / | |
102 | ||
103 | 102 | # odd, found on Win2003 |
104 | 103 | next unless keys %$data > 2; |
105 | 104 | |
106 | 105 | # See bug #927 |
107 | 106 | # http://stackoverflow.com/questions/2639513/duplicate-entries-in-uninstall-registry-key-when-compiling-list-of-installed-soft |
108 | 107 | next if $data->{'/SystemComponent'}; |
108 | ||
109 | my $guid = $rawGuid; | |
110 | $guid =~ s/\/$//; # drop the tailing / | |
109 | 111 | |
110 | 112 | my $software = { |
111 | 113 | FROM => "registry", |
119 | 121 | URL_INFO_ABOUT => encodeFromRegistry($data->{'/URLInfoAbout'}), |
120 | 122 | UNINSTALL_STRING => encodeFromRegistry($data->{'/UninstallString'}), |
121 | 123 | INSTALLDATE => _dateFormat($data->{'/InstallDate'}), |
122 | VERSION_MINOR => hex2dec($data->{'/VersionMinor'}), | |
123 | VERSION_MAJOR => hex2dec($data->{'/VersionMajor'}), | |
124 | NO_REMOVE => $data->{'/NoRemove'} && | |
125 | $data->{'/NoRemove'} =~ /1/, | |
124 | VERSION_MINOR => hex2dec($data->{'/MinorVersion'}), | |
125 | VERSION_MAJOR => hex2dec($data->{'/MajorVersion'}), | |
126 | NO_REMOVE => hex2dec($data->{'/NoRemove'}), | |
126 | 127 | IS64BIT => $is64bit, |
127 | 128 | GUID => $guid, |
128 | 129 | }; |
133 | 134 | # avoid duplicates |
134 | 135 | next if $seen->{$software->{NAME}}->{$software->{VERSION}}++; |
135 | 136 | |
136 | $inventory->addEntry( | |
137 | section => 'SOFTWARES', | |
138 | entry => $software, | |
139 | ); | |
137 | push @softwares, $software; | |
140 | 138 | } |
139 | ||
140 | return @softwares; | |
141 | 141 | } |
142 | 142 | |
143 | 143 | 1; |
21 | 21 | DRIVES => [ qw/CREATEDATE DESCRIPTION FREE FILESYSTEM LABEL LETTER |
22 | 22 | SERIAL SYSTEMDRIVE TOTAL TYPE VOLUMN/ ], |
23 | 23 | ENVS => [ qw/KEY VAL/ ], |
24 | INPUTS => [ qw/CAPTION DESCRIPTION INTERFACE LAYOUT POINTTYPE TYPE/ ], | |
24 | INPUTS => [ qw/NAME MANUFACTURER CAPTION DESCRIPTION INTERFACE LAYOUT | |
25 | POINTINGTYPE TYPE/ ], | |
25 | 26 | MEMORIES => [qw/CAPACITY CAPTION FORMFACTOR REMOVABLE PURPOSE SPEED |
26 | 27 | SERIALNUMBER TYPE DESCRIPTION NUMSLOTS/ ], |
27 | 28 | MODEMS => [ qw/DESCRIPTION NAME/ ], |
28 | 29 | MONITORS => [ qw/BASE64 CAPTION DESCRIPTION MANUFACTURER SERIAL |
29 | 30 | UUENCODE/ ], |
30 | 31 | NETWORKS => [ qw/DESCRIPTION DRIVER IPADDRESS IPADDRESS6 IPDHCP IPGATEWAY |
31 | IPMASK IPSUBNET MACADDR MTU PCISLOT STATUS TYPE | |
32 | VIRTUALDEV SLAVES SPEED MANAGEMENT BSSID SSID/ ], | |
32 | IPMASK IPSUBNET MACADDR MTU PCISLOT PNPDEVICEID STATUS | |
33 | TYPE VIRTUALDEV SLAVES SPEED MANAGEMENT BSSID SSID/ ], | |
33 | 34 | PORTS => [ qw/CAPTION DESCRIPTION NAME TYPE/ ], |
34 | 35 | PROCESSES => [ qw/USER PID CPUUSAGE MEM VIRTUALMEMORY TTY STARTED CMD/ ], |
35 | 36 | REGISTRY => [ qw/NAME REGVALUE HIVE/ ], |
37 | 38 | SOFTWARES => [ qw/COMMENTS FILESIZE FOLDER FROM HELPLINK INSTALLDATE NAME |
38 | 39 | NO_REMOVE RELEASE_TYPE PUBLISHER UNINSTALL_STRING |
39 | 40 | URL_INFO_ABOUT VERSION VERSION_MINOR VERSION_MAJOR |
40 | IS64BIT GUID/ ], | |
41 | SOUNDS => [ qw/DESCRIPTION MANUFACTURER NAME/ ], | |
41 | IS64BIT GUID RELEASETYPE/ ], | |
42 | SOUNDS => [ qw/CAPTION DESCRIPTION MANUFACTURER NAME/ ], | |
42 | 43 | STORAGES => [ qw/DESCRIPTION DISKSIZE INTERFACE MANUFACTURER MODEL NAME |
43 | 44 | TYPE SERIAL SERIALNUMBER FIRMWARE SCSI_COID SCSI_CHID |
44 | 45 | SCSI_UNID SCSI_LUN WWN/ ], |
13 | 13 | |
14 | 14 | our $VERSION = '1.0'; |
15 | 15 | |
16 | sub isEnabled { | |
17 | my ($self, $response) = @_; | |
18 | ||
19 | # always enabled for local target | |
20 | return 1 unless | |
21 | $self->{target}->isa('FusionInventory::Agent::Target::Server'); | |
22 | ||
23 | if ($self->{config}->{force}) { | |
24 | $self->{logger}->debug("Prolog response ignored"); | |
25 | return 1; | |
26 | } | |
27 | ||
28 | my $content = $response->getContent(); | |
29 | if (!$content || !$content->{RESPONSE} || $content->{RESPONSE} ne 'SEND') { | |
30 | $self->{logger}->debug("No inventory requested in the prolog response"); | |
31 | return; | |
32 | } | |
33 | ||
34 | $self->{registry} = $response->getOptionsInfoByName('REGISTRY'); | |
35 | return 1; | |
36 | } | |
37 | ||
16 | 38 | sub run { |
17 | my ($self) = @_; | |
18 | ||
19 | if ($self->{target}->isa('FusionInventory::Agent::Target::Server')) { | |
20 | die "No server response" unless $self->{prologresp}; | |
21 | ||
22 | if ($self->{config}->{force}) { | |
23 | $self->{logger}->debug( | |
24 | "Force enable, ignore prolog and run inventory." | |
25 | ); | |
26 | } else { | |
27 | my $content = $self->{prologresp}->getContent(); | |
28 | if (!($content && $content->{RESPONSE} && $content->{RESPONSE} =~ /^SEND$/)) { | |
29 | $self->{logger}->debug("No inventory requested in the prolog"); | |
30 | return; | |
31 | } | |
32 | } | |
33 | } | |
39 | my ($self, %params) = @_; | |
40 | ||
41 | $self->{logger}->debug("FusionInventory Inventory task $VERSION"); | |
34 | 42 | |
35 | 43 | $self->{modules} = {}; |
36 | 44 | |
82 | 90 | $self->{logger}->error("Can't write to $file: $ERRNO"); |
83 | 91 | } |
84 | 92 | } elsif ($self->{target}->isa('FusionInventory::Agent::Target::Server')) { |
93 | my $client = FusionInventory::Agent::HTTP::Client::OCS->new( | |
94 | logger => $self->{logger}, | |
95 | user => $params{user}, | |
96 | password => $params{password}, | |
97 | proxy => $params{proxy}, | |
98 | ca_cert_file => $params{ca_cert_file}, | |
99 | ca_cert_dir => $params{ca_cert_dir}, | |
100 | no_ssl_check => $params{no_ssl_check}, | |
101 | ); | |
85 | 102 | |
86 | 103 | my $message = FusionInventory::Agent::XML::Query::Inventory->new( |
87 | 104 | deviceid => $self->{deviceid}, |
88 | 105 | content => $inventory->getContent() |
89 | 106 | ); |
90 | 107 | |
91 | my $response = $self->{client}->send( | |
108 | my $response = $client->send( | |
92 | 109 | url => $self->{target}->getUrl(), |
93 | 110 | message => $message |
94 | 111 | ); |
138 | 155 | params => { |
139 | 156 | datadir => $self->{datadir}, |
140 | 157 | logger => $self->{logger}, |
141 | prologresp => $self->{prologresp}, | |
158 | registry => $self->{registry}, | |
142 | 159 | no_software => $self->{config}->{'no-software'}, |
143 | 160 | no_printer => $self->{config}->{'no-printer'}, |
144 | 161 | scan_homedirs => $self->{config}->{'scan-homedirs'}, |
209 | 226 | $self->_runModule($other_module, $inventory); |
210 | 227 | } |
211 | 228 | |
212 | $logger->debug ("Running $module"); | |
229 | $logger->debug("Running $module"); | |
213 | 230 | |
214 | 231 | runFunction( |
215 | 232 | module => $module, |
219 | 236 | datadir => $self->{datadir}, |
220 | 237 | inventory => $inventory, |
221 | 238 | logger => $self->{logger}, |
222 | prologresp => $self->{prologresp}, | |
239 | registry => $self->{registry}, | |
223 | 240 | no_software => $self->{config}->{no_software}, |
224 | 241 | no_printer => $self->{config}->{no_printer}, |
225 | 242 | scan_homedirs => $self->{config}->{'scan-homedirs'}, |
299 | 316 | my $tpp = XML::TreePP->new(indent => 2); |
300 | 317 | print {$params{handle}} $tpp->write({ |
301 | 318 | REQUEST => { |
302 | CONTENT => $params{inventory}->{content} | |
319 | CONTENT => $params{inventory}->{content}, | |
320 | DEVICEID => $self->{deviceid}, | |
321 | QUERY => "INVENTORY", | |
303 | 322 | } |
304 | 323 | }); |
305 | 324 | |
307 | 326 | } |
308 | 327 | |
309 | 328 | if ($params{format} eq 'html') { |
310 | ||
329 | Text::Template->require(); | |
311 | 330 | my $template = Text::Template->new( |
312 | 331 | TYPE => 'FILE', SOURCE => "$self->{datadir}/html/inventory.tpl" |
313 | 332 | ); |
10 | 10 | use English qw(-no_match_vars); |
11 | 11 | use Socket; |
12 | 12 | |
13 | use FusionInventory::Agent::Tools; | |
14 | use FusionInventory::Agent::Tools::Linux; | |
13 | 15 | use FusionInventory::Agent::Tools::Network; |
14 | 16 | |
15 | 17 | our $VERSION = '1.0'; |
16 | 18 | |
17 | sub run { | |
18 | my ($self) = @_; | |
19 | sub isEnabled { | |
20 | my ($self, $response) = @_; | |
19 | 21 | |
20 | if (!$self->{target}->isa('FusionInventory::Agent::Target::Server')) { | |
21 | $self->{logger}->debug("No server. Exiting..."); | |
22 | return unless | |
23 | $self->{target}->isa('FusionInventory::Agent::Target::Server'); | |
24 | ||
25 | my $options = $self->getOptionsFromServer( | |
26 | $response, 'WAKEONLAN', 'WakeOnLan' | |
27 | ); | |
28 | return unless $options; | |
29 | ||
30 | my $target = $options->{PARAM}->[0]->{MAC}; | |
31 | if (!$target) { | |
32 | $self->{logger}->debug("No mac address defined in the prolog response"); | |
22 | 33 | return; |
23 | 34 | } |
24 | 35 | |
25 | my $response = $self->{prologresp}; | |
26 | if (!$response) { | |
27 | $self->{logger}->debug("No server response. Exiting..."); | |
36 | if (!$target !~ /^$mac_address_pattern$/) { | |
37 | $self->{logger}->debug("invalid MAC address $target"); | |
28 | 38 | return; |
29 | 39 | } |
30 | 40 | |
31 | my $options = $response->getOptionsInfoByName('WAKEONLAN'); | |
32 | if (!$options) { | |
33 | $self->{logger}->debug( | |
34 | "No wake on lan requested in the prolog, exiting" | |
35 | ); | |
36 | return; | |
37 | } | |
41 | $self->{options} = $options; | |
42 | return 1; | |
43 | } | |
38 | 44 | |
39 | my $macaddress = $self->{WAKEONLAN}->{PARAM}->[0]->{MAC}; | |
45 | sub run { | |
46 | my ($self, %params) = @_; | |
40 | 47 | |
41 | return unless defined $macaddress; | |
48 | $self->{logger}->debug("FusionInventory WakeOnLan task $VERSION"); | |
42 | 49 | |
43 | if ($macaddress !~ /^$mac_address_pattern$/) { | |
44 | die "invalid MAC address $macaddress, exiting"; | |
45 | } | |
46 | $macaddress =~ s/://g; | |
50 | my $options = $self->{options}; | |
51 | my $target = $options->{PARAM}->[0]->{MAC}; | |
52 | $target =~ s/://g; | |
47 | 53 | |
48 | 54 | # Linux only |
49 | 55 | eval { |
52 | 58 | setsockopt(SOCKET, SOL_SOCKET, SO_BROADCAST, 1) |
53 | 59 | or warn "Can't do setsockopt: $ERRNO\n"; |
54 | 60 | |
55 | open my $handle, '-|', '/sbin/ifconfig -a' | |
56 | or die "Can't run /sbin/ifconfig: $ERRNO"; | |
57 | while (my $line = <$handle>) { | |
58 | next unless $line =~ /(\S+) \s+ Link \s \S+ \s+ HWaddr \s (\S+)/x; | |
59 | my $netName = $1; | |
60 | my $netMac = $2; | |
61 | $self->{logger}->debug( | |
62 | "Send magic packet to $macaddress directly on card driver" | |
63 | ); | |
64 | $netMac =~ s/://g; | |
61 | my $interface = | |
62 | first { $_->{MACADDR} } | |
63 | getInterfacesFromIfconfig(logger => $self->{logger}); | |
64 | my $source = $interface->{MACADDR}; | |
65 | $source =~ s/://g; | |
65 | 66 | |
66 | my $magic_packet = | |
67 | (pack('H12', $macaddress)) . | |
68 | (pack('H12', $netMac)) . | |
69 | (pack('H4', "0842")); | |
70 | $magic_packet .= chr(0xFF) x 6 . (pack('H12', $macaddress) x 16); | |
71 | my $destination = pack("Sa14", 0, $netName); | |
72 | send(SOCKET, $magic_packet, 0, $destination) | |
73 | or warn "Couldn't send packet: $ERRNO"; | |
74 | } | |
75 | close $handle; | |
67 | $self->{logger}->debug( | |
68 | "Sending magic packet to $target as ethernet frame" | |
69 | ); | |
70 | ||
71 | my $magic_packet = | |
72 | (pack('H12', $target)) . | |
73 | (pack('H12', $source)) . | |
74 | (pack('H4', "0842")); | |
75 | $magic_packet .= chr(0xFF) x 6 . (pack('H12', $target) x 16); | |
76 | my $destination = pack("Sa14", 0, $interface->{DESCRIPTION}); | |
77 | send(SOCKET, $magic_packet, 0, $destination) | |
78 | or warn "Couldn't send packet: $ERRNO"; | |
76 | 79 | # TODO : For FreeBSD, send to /dev/bpf .... |
77 | 80 | }; |
78 | 81 | |
83 | 86 | socket(SOCKET, PF_INET, SOCK_DGRAM, getprotobyname('udp')); |
84 | 87 | my $magic_packet = |
85 | 88 | chr(0xFF) x 6 . |
86 | (pack('H12', $macaddress) x 16); | |
89 | (pack('H12', $target) x 16); | |
87 | 90 | my $sinbroadcast = sockaddr_in("9", inet_aton("255.255.255.255")); |
88 | 91 | $self->{logger}->debug( |
89 | "Send magic packet to $macaddress in UDP mode (degraded wol)" | |
92 | "Sending magic packet to $target as UDP packetm" | |
90 | 93 | ); |
91 | 94 | send(SOCKET, $magic_packet, 0, $sinbroadcast); |
92 | 95 | }; |
14 | 14 | die 'no target parameter' unless $params{target}; |
15 | 15 | |
16 | 16 | my $self = { |
17 | logger => $params{logger} || | |
18 | FusionInventory::Agent::Logger->new(), | |
19 | config => $params{config}, | |
20 | confdir => $params{confdir}, | |
21 | datadir => $params{datadir}, | |
22 | target => $params{target}, | |
23 | prologresp => $params{prologresp}, | |
24 | client => $params{client}, | |
25 | deviceid => $params{deviceid} | |
17 | logger => $params{logger} || | |
18 | FusionInventory::Agent::Logger->new(), | |
19 | config => $params{config}, | |
20 | confdir => $params{confdir}, | |
21 | datadir => $params{datadir}, | |
22 | target => $params{target}, | |
23 | deviceid => $params{deviceid}, | |
26 | 24 | }; |
27 | 25 | bless $self, $class; |
28 | 26 | |
29 | 27 | return $self; |
28 | } | |
29 | ||
30 | sub getOptionsFromServer { | |
31 | my ($self, $response, $name, $feature) = @_; | |
32 | ||
33 | if (!$response) { | |
34 | $self->{logger}->debug("No server response"); | |
35 | return; | |
36 | } | |
37 | ||
38 | my $options = $response->getOptionsInfoByName($name); | |
39 | if (!$options) { | |
40 | $self->{logger}->debug("No $feature requested in the prolog"); | |
41 | return; | |
42 | } | |
43 | ||
44 | return $options; | |
30 | 45 | } |
31 | 46 | |
32 | 47 | sub getModules { |
98 | 113 | |
99 | 114 | This is the method to be implemented by each subclass. |
100 | 115 | |
116 | =head2 getOptionsFromServer($response, $name, $feature) | |
117 | ||
118 | Get task-specific options in server response to prolog message. | |
119 | ||
101 | 120 | =head2 getModules($prefix) |
102 | 121 | |
103 | 122 | Return a list of modules for this task. All modules installed at the same |
8 | 8 | |
9 | 9 | use FusionInventory::Agent::Tools; |
10 | 10 | use FusionInventory::Agent::Tools::Unix; |
11 | use FusionInventory::Agent::Tools::Network; | |
11 | 12 | |
12 | 13 | our @EXPORT = qw( |
13 | 14 | getDevicesFromUdev |
15 | 16 | getDevicesFromProc |
16 | 17 | getCPUsFromProc |
17 | 18 | getSerialnumber |
19 | getInterfacesFromIfconfig | |
20 | getInterfacesFromIp | |
18 | 21 | ); |
19 | 22 | |
20 | 23 | memoize('getDevicesFromUdev'); |
253 | 256 | return $serial; |
254 | 257 | } |
255 | 258 | |
259 | sub getInterfacesFromIfconfig { | |
260 | my %params = ( | |
261 | command => '/sbin/ifconfig -a', | |
262 | @_ | |
263 | ); | |
264 | my $handle = getFileHandle(%params); | |
265 | return unless $handle; | |
266 | ||
267 | my @interfaces; | |
268 | my $interface; | |
269 | ||
270 | while (my $line = <$handle>) { | |
271 | if ($line =~ /^$/) { | |
272 | # end of interface section | |
273 | push @interfaces, $interface if $interface; | |
274 | next; | |
275 | } | |
276 | ||
277 | if ($line =~ /^(\S+)/) { | |
278 | # new interface | |
279 | $interface = { | |
280 | STATUS => 'Down', | |
281 | DESCRIPTION => $1 | |
282 | } | |
283 | } | |
284 | if ($line =~ /inet addr:($ip_address_pattern)/i) { | |
285 | $interface->{IPADDRESS} = $1; | |
286 | } | |
287 | if ($line =~ /Mask:($ip_address_pattern)/) { | |
288 | $interface->{IPMASK} = $1; | |
289 | } | |
290 | if ($line =~ /inet6 addr: (\S+)/i) { | |
291 | $interface->{IPADDRESS6} = $1; | |
292 | } | |
293 | if ($line =~ /hwadd?r\s+($mac_address_pattern)/i) { | |
294 | $interface->{MACADDR} = $1; | |
295 | } | |
296 | if ($line =~ /^\s+UP\s/) { | |
297 | $interface->{STATUS} = 'Up'; | |
298 | } | |
299 | if ($line =~ /link encap:(\S+)/i) { | |
300 | $interface->{TYPE} = $1; | |
301 | } | |
302 | ||
303 | } | |
304 | close $handle; | |
305 | ||
306 | return @interfaces; | |
307 | } | |
308 | sub getInterfacesFromIp { | |
309 | my %params = ( | |
310 | command => '/sbin/ip addr show', | |
311 | @_ | |
312 | ); | |
313 | ||
314 | my $handle = getFileHandle(%params); | |
315 | return unless $handle; | |
316 | ||
317 | my @interfaces; | |
318 | my $interface; | |
319 | ||
320 | while (my $line = <$handle>) { | |
321 | chomp $line; | |
322 | if ($line =~ /^\d+:\s+(\S+): .*(UP|DOWN)/) { | |
323 | push @interfaces, $interface if $interface; | |
324 | $interface = { | |
325 | DESCRIPTION => $1, | |
326 | STATUS => ucfirst(lc($2)) | |
327 | }; | |
328 | } elsif ($line =~ /link\/ether ($mac_address_pattern)/) { | |
329 | $interface->{MACADDR} = $1; | |
330 | } elsif ($line =~ /inet6 (\S+)\//) { | |
331 | $interface->{IPADDRESS6} = $1; | |
332 | } elsif ($line =~ /inet ($ip_address_pattern)\/(\d{1,3})/) { | |
333 | $interface->{IPADDRESS} = $1; | |
334 | $interface->{IPMASK} = getNetworkMask($1, $2); | |
335 | $interface->{IPSUBNET} = getSubnetAddress( | |
336 | $interface->{IPADDRESS}, $interface->{IPMASK} | |
337 | ); | |
338 | } | |
339 | } | |
340 | ||
341 | return @interfaces; | |
342 | } | |
343 | ||
256 | 344 | 1; |
257 | 345 | __END__ |
258 | 346 | |
335 | 423 | =item file the file to use |
336 | 424 | |
337 | 425 | =back |
426 | ||
427 | =head2 getInterfacesFromIfconfig(%params) | |
428 | ||
429 | Returns the list of interfaces, by parsing ifconfig command output. | |
430 | ||
431 | Availables parameters: | |
432 | ||
433 | =over | |
434 | ||
435 | =item logger a logger object | |
436 | ||
437 | =item command the command to use (default: /sbin/ifconfig -a) | |
438 | ||
439 | =item file the file to use | |
440 | ||
441 | =back | |
442 | ||
443 | =head2 getInterfacesFromIp(%params) | |
444 | ||
445 | Returns the list of interfaces, by parsing ip command output. | |
446 | ||
447 | Availables parameters: | |
448 | ||
449 | =over | |
450 | ||
451 | =item logger a logger object | |
452 | ||
453 | =item command the command to use (default: /sbin/ip addr show) | |
454 | ||
455 | =item file the file to use | |
456 | ||
457 | =back |
18 | 18 | getNetworkMask |
19 | 19 | hex2canonical |
20 | 20 | alt2canonical |
21 | getLastNumber | |
22 | 21 | ); |
23 | 22 | |
24 | 23 | my $hex_byte = qr/[0-9A-F]{2}/i; |
63 | 62 | |
64 | 63 | my $binaddress = ip_iptobin($address, 6); |
65 | 64 | my $binmask = ip_iptobin($mask, 6); |
65 | ||
66 | return unless $binaddress && $binmask; | |
67 | ||
66 | 68 | my $binsubnet = $binaddress & $binmask; ## no critic (ProhibitBitwise) |
67 | 69 | |
68 | 70 | return ip_bintoip($binsubnet, 6); |
71 | 73 | sub hex2canonical { |
72 | 74 | my ($address) = @_; |
73 | 75 | |
74 | my @bytes = $address =~ /^(..)(..)(..)(..)$/; | |
76 | my @bytes = $address =~ /^(?:0x)?(..)(..)(..)(..)$/; | |
75 | 77 | return join('.', map { hex($_) } @bytes); |
76 | 78 | } |
77 | 79 | |
78 | 80 | sub alt2canonical { |
79 | 81 | my ($address) = @_; |
80 | 82 | |
81 | my @bytes = $address =~ /^(..)(..)(..)(..)(..)(..)$/; | |
83 | my @bytes = $address =~ /^(?:0x)?(..)(..)(..)(..)(..)(..)$/; | |
82 | 84 | return join(':', @bytes); |
83 | 85 | } |
84 | 86 | |
91 | 93 | |
92 | 94 | my @bytes = $mask =~ /^(\d{8})(\d{8})(\d{8})(\d{8})$/; |
93 | 95 | return join ('.', map { oct('0b' . $_) } @bytes); |
94 | } | |
95 | ||
96 | sub getLastNumber { | |
97 | my ($oid) = @_; | |
98 | ||
99 | my @array = split(/\./, $oid); | |
100 | return $array[-1]; | |
101 | 96 | } |
102 | 97 | |
103 | 98 | 1; |
150 | 145 | =head2 getNetworkMask($address, $prefix) |
151 | 146 | |
152 | 147 | Returns the network mask. |
153 | ||
154 | =head2 getLastNumber($oid) | |
155 | ||
156 | return the last number of an oid. | |
157 |
2 | 2 | use strict; |
3 | 3 | use warnings; |
4 | 4 | use base 'Exporter'; |
5 | ||
6 | use constant SOLARIS_UNKNOWN => 0; | |
7 | use constant SOLARIS_FIRE => 1; | |
8 | use constant SOLARIS_FIRE_V => 2; | |
9 | use constant SOLARIS_FIRE_T => 3; | |
10 | use constant SOLARIS_ENTERPRISE_T => 4; | |
11 | use constant SOLARIS_ENTERPRISE => 5; | |
12 | use constant SOLARIS_I86PC => 6; | |
13 | use constant SOLARIS_CONTAINER => 7; | |
5 | 14 | |
6 | 15 | use English qw(-no_match_vars); |
7 | 16 | |
12 | 21 | getZone |
13 | 22 | getModel |
14 | 23 | getClass |
24 | SOLARIS_UNKNOWN | |
25 | SOLARIS_FIRE | |
26 | SOLARIS_FIRE_V | |
27 | SOLARIS_FIRE_T | |
28 | SOLARIS_ENTERPRISE_T | |
29 | SOLARIS_ENTERPRISE | |
30 | SOLARIS_I86PC | |
31 | SOLARIS_CONTAINER | |
15 | 32 | ); |
16 | 33 | |
17 | 34 | memoize('getZone'); |
49 | 66 | my $model = getModel(); |
50 | 67 | |
51 | 68 | if ($model =~ /SUNW,Sun-Fire-\d/) { |
52 | return 1; | |
69 | return SOLARIS_FIRE; | |
53 | 70 | } |
54 | 71 | |
55 | 72 | if ( |
57 | 74 | $model =~ /SUNW,Netra-T/ or |
58 | 75 | $model =~ /SUNW,Ultra-250/ |
59 | 76 | ) { |
60 | return 2; | |
77 | return SOLARIS_FIRE_V; | |
61 | 78 | } |
62 | 79 | |
63 | 80 | if ( |
64 | 81 | $model =~ /SUNW,Sun-Fire-T\d/ or |
65 | 82 | $model =~ /SUNW,T\d/ |
66 | 83 | ) { |
67 | return 3; | |
84 | return SOLARIS_FIRE_T; | |
68 | 85 | } |
69 | 86 | |
70 | 87 | if ($model =~ /SUNW,SPARC-Enterprise-T\d/) { |
71 | return 4; | |
88 | return SOLARIS_ENTERPRISE_T; | |
72 | 89 | } |
73 | 90 | if ($model =~ /SUNW,SPARC-Enterprise/) { |
74 | return 5; | |
91 | return SOLARIS_ENTERPRISE; | |
75 | 92 | } |
76 | 93 | if ($model eq "i86pc") { |
77 | return 6; | |
94 | return SOLARIS_I86PC; | |
78 | 95 | } |
79 | 96 | if ($model =~ /Solaris Containers/) { |
80 | return 7; | |
97 | return SOLARIS_CONTAINER; | |
81 | 98 | } |
82 | 99 | |
83 | 100 | # unknown class |
84 | return 0; | |
101 | return SOLARIS_UNKNOWN; | |
85 | 102 | } |
86 | 103 | |
87 | 104 |
19 | 19 | getProcessesFromPs |
20 | 20 | getRoutingTable |
21 | 21 | ); |
22 | ||
23 | memoize('getProcessesFromPs'); | |
22 | 24 | |
23 | 25 | sub getDeviceCapacity { |
24 | 26 | my %params = @_; |
43 | 43 | sub encodeFromRegistry { |
44 | 44 | my ($string) = @_; |
45 | 45 | |
46 | return unless $string; | |
46 | ## no critic (ExplicitReturnUndef) | |
47 | return undef unless $string; | |
47 | 48 | |
48 | 49 | if (!$localCodepage) { |
49 | 50 | my $lmachine = $Registry->Open('LMachine', { |
236 | 236 | last SWITCH; |
237 | 237 | } |
238 | 238 | if ($params{string}) { |
239 | ||
240 | 239 | open $handle, "<", \$params{string} or die; |
240 | last SWITCH; | |
241 | 241 | } |
242 | die "neither command nor file parameter given"; | |
242 | die "neither command, file or string parameter given"; | |
243 | 243 | } |
244 | 244 | |
245 | 245 | return $handle; |
345 | 345 | sub hex2char { |
346 | 346 | my ($value) = @_; |
347 | 347 | |
348 | return unless $value; | |
348 | ## no critic (ExplicitReturnUndef) | |
349 | return undef unless $value; | |
349 | 350 | return $value unless $value =~ /^0x/; |
350 | 351 | |
351 | 352 | $value =~ s/^0x//; |
357 | 358 | sub hex2dec { |
358 | 359 | my ($value) = @_; |
359 | 360 | |
360 | return unless $value; | |
361 | ## no critic (ExplicitReturnUndef) | |
362 | return undef unless $value; | |
361 | 363 | return $value unless $value =~ /^0x/; |
362 | 364 | |
363 | 365 | return oct($value); |
366 | 368 | sub dec2hex { |
367 | 369 | my ($value) = @_; |
368 | 370 | |
369 | return unless $value; | |
371 | ## no critic (ExplicitReturnUndef) | |
372 | return undef unless $value; | |
370 | 373 | return $value if $value =~ /^0x/; |
371 | 374 | |
372 | 375 | return sprintf("0x%x", $value); |
516 | 519 | |
517 | 520 | =head2 getFileHandle(%params) |
518 | 521 | |
519 | Returns an open file handle on either a command output, or a file. | |
520 | ||
521 | =over | |
522 | ||
523 | =item logger a logger object | |
524 | ||
525 | =item command the exact command to use | |
522 | Returns an open file handle on either a command output, a file, or a string. | |
523 | ||
524 | =over | |
525 | ||
526 | =item logger a logger object | |
527 | ||
528 | =item command the command to use | |
526 | 529 | |
527 | 530 | =item file the file to use, as an alternative to the command |
531 | ||
532 | =item string the string to use, as an alternative to the command | |
528 | 533 | |
529 | 534 | =back |
530 | 535 |
6 | 6 | use English qw(-no_match_vars); |
7 | 7 | use Sys::Hostname; |
8 | 8 | use UNIVERSAL::require; |
9 | use File::Glob; | |
9 | 10 | |
10 | 11 | use FusionInventory::Agent::Config; |
11 | 12 | use FusionInventory::Agent::HTTP::Client::OCS; |
19 | 20 | use FusionInventory::Agent::Tools; |
20 | 21 | use FusionInventory::Agent::XML::Query::Prolog; |
21 | 22 | |
22 | our $VERSION = '2.1.9901'; | |
23 | our $VERSION = '2.1.9902'; | |
23 | 24 | our $VERSION_STRING = |
24 | 25 | "FusionInventory unified agent for UNIX, Linux and MacOSX ($VERSION)"; |
25 | 26 | our $AGENT_STRING = |
26 | 27 | "FusionInventory-Agent_v$VERSION"; |
27 | ||
28 | my @tasks = qw/ | |
29 | Inventory | |
30 | WakeOnLan | |
31 | SNMPQuery | |
32 | NetDiscovery | |
33 | Deploy | |
34 | ESX | |
35 | /; | |
36 | 28 | |
37 | 29 | sub new { |
38 | 30 | my ($class, %params) = @_; |
45 | 37 | }; |
46 | 38 | bless $self, $class; |
47 | 39 | |
40 | return $self; | |
41 | } | |
42 | ||
43 | sub init { | |
44 | my ($self, %params) = @_; | |
45 | ||
48 | 46 | my $config = FusionInventory::Agent::Config->new( |
49 | confdir => $params{confdir}, | |
47 | confdir => $self->{confdir}, | |
50 | 48 | options => $params{options}, |
51 | 49 | ); |
52 | 50 | $self->{config} = $config; |
165 | 163 | |
166 | 164 | $_->setShared() foreach $scheduler->getTargets(); |
167 | 165 | |
168 | $self->{_server} = FusionInventory::Agent::HTTP::Server->new( | |
166 | $self->{server} = FusionInventory::Agent::HTTP::Server->new( | |
169 | 167 | logger => $logger, |
170 | 168 | scheduler => $scheduler, |
171 | 169 | agent => $self, |
177 | 175 | } |
178 | 176 | } |
179 | 177 | |
178 | # compute list of allowed tasks | |
179 | my %available = $self->getAvailableTasks(); | |
180 | my %disabled = map { lc($_) => 1 } @{$config->{'no-task'}}; | |
181 | my @allowed = grep { !$disabled{lc($_)} } keys %available; | |
182 | $self->{tasks} = \@allowed; | |
183 | ||
180 | 184 | $logger->debug("FusionInventory Agent initialised"); |
181 | ||
182 | return $self; | |
183 | } | |
184 | ||
185 | sub _isAlreadyRunning { | |
186 | my ($self) = @_; | |
187 | ||
188 | Proc::PID::File->require(); | |
189 | if ($EVAL_ERROR) { | |
190 | $self->{logger}->debug( | |
191 | 'Proc::PID::File unavailable, unable to check for running agent' | |
192 | ); | |
193 | return 0; | |
194 | } | |
195 | ||
196 | return Proc::PID::File->running(); | |
197 | } | |
198 | ||
199 | sub _getHostname { | |
200 | ||
201 | # use hostname directly under Unix | |
202 | return hostname() if $OSNAME ne 'MSWin32'; | |
203 | ||
204 | # otherwise, use Win32 API | |
205 | Encode->require(); | |
206 | Encode->import(); | |
207 | Win32::API->require(); | |
208 | ||
209 | my $getComputerName = Win32::API->new( | |
210 | "kernel32", "GetComputerNameExW", ["I", "P", "P"], "N" | |
211 | ); | |
212 | my $lpBuffer = "\x00" x 1024; | |
213 | my $N = 1024; #pack ("c4", 160,0,0,0); | |
214 | ||
215 | $getComputerName->Call(3, $lpBuffer, $N); | |
216 | ||
217 | # GetComputerNameExW returns the string in UTF16, we have to change | |
218 | # it to UTF8 | |
219 | return encode( | |
220 | "UTF-8", substr(decode("UCS-2le", $lpBuffer), 0, ord $N) | |
221 | ); | |
222 | } | |
223 | ||
224 | sub _loadState { | |
225 | my ($self) = @_; | |
226 | ||
227 | my $data = $self->{storage}->restore(name => 'FusionInventory-Agent'); | |
228 | ||
229 | $self->{token} = $data->{token} if $data->{token}; | |
230 | $self->{deviceid} = $data->{deviceid} if $data->{deviceid}; | |
231 | } | |
232 | ||
233 | sub _saveState { | |
234 | my ($self) = @_; | |
235 | ||
236 | $self->{storage}->save( | |
237 | name => 'FusionInventory-Agent', | |
238 | data => { | |
185 | } | |
186 | ||
187 | sub run { | |
188 | my ($self) = @_; | |
189 | ||
190 | $self->{status} = 'waiting'; | |
191 | ||
192 | # endless loop in server mode | |
193 | while (my $target = $self->{scheduler}->getNextTarget()) { | |
194 | eval { | |
195 | $self->_runTarget($target); | |
196 | }; | |
197 | $self->{logger}->fault($EVAL_ERROR) if $EVAL_ERROR; | |
198 | $target->resetNextRunDate(); | |
199 | } | |
200 | } | |
201 | ||
202 | sub _runTarget { | |
203 | my ($self, $target) = @_; | |
204 | ||
205 | # the prolog dialog must be done once for all tasks, | |
206 | # but only for server targets | |
207 | my $response; | |
208 | if ($target->isa('FusionInventory::Agent::Target::Server')) { | |
209 | my $client = FusionInventory::Agent::HTTP::Client::OCS->new( | |
210 | logger => $self->{logger}, | |
211 | user => $self->{config}->{user}, | |
212 | password => $self->{config}->{password}, | |
213 | proxy => $self->{config}->{proxy}, | |
214 | ca_cert_file => $self->{config}->{'ca-cert-file'}, | |
215 | ca_cert_dir => $self->{config}->{'ca-cert-dir'}, | |
216 | no_ssl_check => $self->{config}->{'no-ssl-check'}, | |
217 | ); | |
218 | ||
219 | my $prolog = FusionInventory::Agent::XML::Query::Prolog->new( | |
239 | 220 | token => $self->{token}, |
240 | 221 | deviceid => $self->{deviceid}, |
241 | } | |
242 | ); | |
243 | } | |
244 | ||
245 | sub run { | |
246 | my ($self) = @_; | |
247 | ||
248 | my $config = $self->{config}; | |
222 | ); | |
223 | ||
224 | $response = $client->send( | |
225 | url => $target->getUrl(), | |
226 | message => $prolog | |
227 | ); | |
228 | die "No answer from the server" unless $response; | |
229 | ||
230 | # update target | |
231 | my $content = $response->getContent(); | |
232 | if (defined($content->{PROLOG_FREQ})) { | |
233 | $target->setMaxDelay($content->{PROLOG_FREQ} * 3600); | |
234 | } | |
235 | } | |
236 | ||
237 | foreach my $name (@{$self->{tasks}}) { | |
238 | eval { | |
239 | $self->_runTask($target, $name, $response); | |
240 | }; | |
241 | $self->{logger}->error($EVAL_ERROR) if $EVAL_ERROR; | |
242 | $self->{status} = 'waiting'; | |
243 | } | |
244 | } | |
245 | ||
246 | sub _runTask { | |
247 | my ($self, $target, $name, $response) = @_; | |
248 | ||
249 | my $class = "FusionInventory::Agent::Task::$name"; | |
250 | my $task = $class->new( | |
251 | config => $self->{config}, | |
252 | confdir => $self->{confdir}, | |
253 | datadir => $self->{datadir}, | |
254 | logger => $self->{logger}, | |
255 | target => $target, | |
256 | deviceid => $self->{deviceid}, | |
257 | ); | |
258 | ||
259 | if (!$task->isEnabled($response)) { | |
260 | $self->{logger}->info("task $name is not enabled"); | |
261 | return; | |
262 | } | |
263 | ||
264 | $self->{status} = "running task $name"; | |
265 | ||
266 | if ($self->{config}->{daemon} || $self->{config}->{service}) { | |
267 | # daemon mode: run each task in a child process | |
268 | if (my $pid = fork()) { | |
269 | # parent | |
270 | waitpid($pid, 0); | |
271 | } else { | |
272 | # child | |
273 | die "fork failed: $ERRNO" unless defined $pid; | |
274 | ||
275 | $self->{logger}->debug("running task $name in process $PID"); | |
276 | $task->run( | |
277 | user => $self->{config}->{user}, | |
278 | password => $self->{config}->{password}, | |
279 | proxy => $self->{config}->{proxy}, | |
280 | ca_cert_file => $self->{config}->{'ca-cert-file'}, | |
281 | ca_cert_dir => $self->{config}->{'ca-cert-dir'}, | |
282 | no_ssl_check => $self->{config}->{'no-ssl-check'}, | |
283 | ); | |
284 | exit(0); | |
285 | } | |
286 | } else { | |
287 | # standalone mode: run each task directly | |
288 | $self->{logger}->debug("running task $name"); | |
289 | $task->run( | |
290 | user => $self->{config}->{user}, | |
291 | password => $self->{config}->{password}, | |
292 | proxy => $self->{config}->{proxy}, | |
293 | ca_cert_file => $self->{config}->{'ca-cert-file'}, | |
294 | ca_cert_dir => $self->{config}->{'ca-cert-dir'}, | |
295 | no_ssl_check => $self->{config}->{'no-ssl-check'}, | |
296 | ); | |
297 | } | |
298 | } | |
299 | ||
300 | sub getToken { | |
301 | my ($self) = @_; | |
302 | return $self->{token}; | |
303 | } | |
304 | ||
305 | sub resetToken { | |
306 | my ($self) = @_; | |
307 | $self->{token} = _computeToken(); | |
308 | } | |
309 | ||
310 | sub getStatus { | |
311 | my ($self) = @_; | |
312 | return $self->{status}; | |
313 | } | |
314 | ||
315 | sub getAvailableTasks { | |
316 | my ($self) = @_; | |
317 | ||
249 | 318 | my $logger = $self->{logger}; |
250 | my $scheduler = $self->{scheduler}; | |
251 | $self->{status} = 'waiting'; | |
252 | ||
253 | my $status = 0; | |
254 | ||
255 | while (my $target = $scheduler->getNextTarget()) { | |
256 | eval { | |
257 | my $prologresp; | |
258 | my $client; | |
259 | if ($target->isa('FusionInventory::Agent::Target::Server')) { | |
260 | ||
261 | $client = FusionInventory::Agent::HTTP::Client::OCS->new( | |
262 | logger => $logger, | |
263 | user => $self->{config}->{user}, | |
264 | password => $self->{config}->{password}, | |
265 | proxy => $self->{config}->{proxy}, | |
266 | ca_cert_file => $self->{config}->{'ca-cert-file'}, | |
267 | ca_cert_dir => $self->{config}->{'ca-cert-dir'}, | |
268 | no_ssl_check => $self->{config}->{'no-ssl-check'}, | |
269 | ); | |
270 | ||
271 | my $prolog = FusionInventory::Agent::XML::Query::Prolog->new( | |
272 | token => $self->{token}, | |
273 | deviceid => $self->{deviceid}, | |
274 | ); | |
275 | ||
276 | $prologresp = $client->send( | |
277 | url => $target->getUrl(), | |
278 | message => $prolog | |
279 | ); | |
280 | ||
281 | if (!$prologresp) { | |
282 | $logger->error("No answer from the server"); | |
283 | $target->resetNextRunDate(); | |
284 | return; | |
285 | } | |
286 | ||
287 | # update target | |
288 | my $content = $prologresp->getContent(); | |
289 | if (defined($content->{PROLOG_FREQ})) { | |
290 | $target->setMaxDelay($content->{PROLOG_FREQ} * 3600); | |
291 | } | |
292 | } | |
293 | ||
294 | # index list of disabled task for fast lookup | |
295 | my %disabled = map { $_ => 1 } @{$config->{'no-task'}}; | |
296 | ||
297 | foreach my $module (@tasks) { | |
298 | ||
299 | next if $disabled{lc($module)}; | |
300 | ||
301 | my $package = "FusionInventory::Agent::Task::$module"; | |
302 | if (!$package->require()) { | |
303 | $logger->info("task $module is not available"); | |
304 | $logger->debug2("task $module compile error: $EVAL_ERROR"); | |
305 | next; | |
306 | } | |
307 | if (!$package->isa('FusionInventory::Agent::Task')) { | |
308 | $logger->info( | |
309 | "task $module is not compatible with this agent " . | |
310 | "($VERSION)" | |
311 | ); | |
312 | next; | |
313 | } | |
314 | ||
315 | $self->{status} = "running task $module"; | |
316 | ||
317 | my $task; | |
318 | eval { | |
319 | $task = $package->new( | |
320 | config => $config, | |
321 | confdir => $self->{confdir}, | |
322 | datadir => $self->{datadir}, | |
323 | logger => $logger, | |
324 | target => $target, | |
325 | prologresp => $prologresp, | |
326 | client => $client, | |
327 | deviceid => $self->{deviceid} | |
328 | ); | |
329 | }; | |
330 | if (!$task) { | |
331 | $logger->info("task $module can't be initialized: ".$EVAL_ERROR); | |
332 | next; | |
333 | } | |
334 | ||
335 | if ($config->{daemon} || $config->{service}) { | |
336 | # daemon mode: run each task in a child process | |
337 | if (my $pid = fork()) { | |
338 | # parent | |
339 | waitpid($pid, 0); | |
340 | } else { | |
341 | # child | |
342 | die "fork failed: $ERRNO" unless defined $pid; | |
343 | ||
344 | $logger->debug( | |
345 | "executing $module in process $$" | |
346 | ); | |
347 | $task->run(); | |
348 | exit(0); | |
349 | } | |
350 | } else { | |
351 | # standalone mode: run each task directly | |
352 | $logger->debug("executing $module"); | |
353 | $task->run(); | |
354 | } | |
355 | } | |
356 | ||
357 | $self->{status} = 'waiting'; | |
358 | ||
359 | }; | |
360 | if ($EVAL_ERROR) { | |
361 | $logger->fault($EVAL_ERROR); | |
362 | $status++; | |
363 | } | |
364 | $target->resetNextRunDate(); | |
365 | } | |
366 | ||
367 | exit $status; | |
368 | } | |
369 | ||
370 | sub getToken { | |
371 | my ($self) = @_; | |
372 | return $self->{token}; | |
373 | } | |
374 | ||
375 | sub resetToken { | |
376 | my ($self) = @_; | |
377 | $self->{token} = _computeToken(); | |
378 | } | |
379 | ||
380 | # compute a random token | |
381 | sub _computeToken { | |
382 | my @chars = ('A'..'Z'); | |
383 | return join('', map { $chars[rand @chars] } 1..8); | |
384 | } | |
385 | ||
386 | # compute an unique agent identifier, based on host name and current time | |
387 | sub _computeDeviceId { | |
388 | my $hostname = _getHostname(); | |
389 | ||
390 | my ($year, $month , $day, $hour, $min, $sec) = | |
391 | (localtime (time))[5, 4, 3, 2, 1, 0]; | |
392 | ||
393 | return sprintf "%s-%02d-%02d-%02d-%02d-%02d-%02d", | |
394 | $hostname, $year + 1900, $month + 1, $day, $hour, $min, $sec; | |
395 | } | |
396 | ||
397 | sub getStatus { | |
398 | my ($self) = @_; | |
399 | return $self->{status}; | |
400 | } | |
401 | ||
402 | sub getKnownTasks { | |
403 | my ($self) = @_; | |
404 | ||
405 | my %tasks; | |
406 | foreach my $module (@tasks) { | |
407 | ||
408 | my $package = "FusionInventory::Agent::Task::$module"; | |
409 | next unless $package->require(); | |
410 | next unless $package->isa('FusionInventory::Agent::Task'); | |
411 | ||
412 | # retrieve version | |
413 | my $version; | |
414 | { | |
415 | no strict 'refs'; ## no critic | |
416 | $version = ${$package . '::VERSION'}; | |
417 | } | |
418 | ||
419 | $tasks{$module} = $version; | |
420 | } | |
421 | ||
422 | return %tasks; | |
423 | } | |
424 | ||
425 | sub getAvailableTasks { | |
426 | my ($self) = @_; | |
427 | ||
428 | 319 | my %tasks; |
429 | 320 | |
430 | 321 | # tasks may be dispatched in every directory referenced in @INC |
434 | 325 | next unless -d "$directory/$subdirectory"; |
435 | 326 | |
436 | 327 | # look for all perl modules here |
437 | foreach my $file (glob("$directory/$subdirectory/*.pm")) { | |
438 | next unless $file =~ m{($subdirectory/\S+\.pm)$}; | |
328 | foreach my $file (File::Glob::glob("$directory/$subdirectory/*.pm")) { | |
329 | next unless $file =~ m{($subdirectory/(\S+)\.pm)$}; | |
439 | 330 | my $module = file2module($1); |
440 | ||
331 | my $name = file2module($2); | |
441 | 332 | # check module |
442 | 333 | # todo: use a child process when running as a server to save memory |
334 | if (!$module->require()) { | |
335 | $logger->debug2("module $module does not compile: $@") if $logger; | |
336 | next; | |
337 | } | |
338 | if (!$module->isa('FusionInventory::Agent::Task')) { | |
339 | $logger->debug2("module $module is not a task") if $logger; | |
340 | next; | |
341 | } | |
342 | ||
443 | 343 | next unless $module->require(); |
444 | 344 | next unless $module->isa('FusionInventory::Agent::Task'); |
445 | 345 | |
453 | 353 | $version = ${$module . '::VERSION'}; |
454 | 354 | } |
455 | 355 | |
456 | $tasks{$module} = $version; | |
356 | $tasks{$name} = $version; | |
457 | 357 | } |
458 | 358 | } |
459 | 359 | |
460 | 360 | return %tasks; |
361 | } | |
362 | ||
363 | sub _isAlreadyRunning { | |
364 | my ($self) = @_; | |
365 | ||
366 | Proc::PID::File->require(); | |
367 | if ($EVAL_ERROR) { | |
368 | $self->{logger}->debug( | |
369 | 'Proc::PID::File unavailable, unable to check for running agent' | |
370 | ); | |
371 | return 0; | |
372 | } | |
373 | ||
374 | return Proc::PID::File->running(); | |
375 | } | |
376 | ||
377 | sub _getHostname { | |
378 | ||
379 | # use hostname directly under Unix | |
380 | return hostname() if $OSNAME ne 'MSWin32'; | |
381 | ||
382 | # otherwise, use Win32 API | |
383 | Encode->require(); | |
384 | Encode->import(); | |
385 | Win32::API->require(); | |
386 | ||
387 | my $getComputerName = Win32::API->new( | |
388 | "kernel32", "GetComputerNameExW", ["I", "P", "P"], "N" | |
389 | ); | |
390 | my $lpBuffer = "\x00" x 1024; | |
391 | my $N = 1024; #pack ("c4", 160,0,0,0); | |
392 | ||
393 | $getComputerName->Call(3, $lpBuffer, $N); | |
394 | ||
395 | # GetComputerNameExW returns the string in UTF16, we have to change | |
396 | # it to UTF8 | |
397 | return encode( | |
398 | "UTF-8", substr(decode("UCS-2le", $lpBuffer), 0, ord $N) | |
399 | ); | |
400 | } | |
401 | ||
402 | sub _loadState { | |
403 | my ($self) = @_; | |
404 | ||
405 | my $data = $self->{storage}->restore(name => 'FusionInventory-Agent'); | |
406 | ||
407 | $self->{token} = $data->{token} if $data->{token}; | |
408 | $self->{deviceid} = $data->{deviceid} if $data->{deviceid}; | |
409 | } | |
410 | ||
411 | sub _saveState { | |
412 | my ($self) = @_; | |
413 | ||
414 | $self->{storage}->save( | |
415 | name => 'FusionInventory-Agent', | |
416 | data => { | |
417 | token => $self->{token}, | |
418 | deviceid => $self->{deviceid}, | |
419 | } | |
420 | ); | |
421 | } | |
422 | ||
423 | # compute a random token | |
424 | sub _computeToken { | |
425 | my @chars = ('A'..'Z'); | |
426 | return join('', map { $chars[rand @chars] } 1..8); | |
427 | } | |
428 | ||
429 | # compute an unique agent identifier, based on host name and current time | |
430 | sub _computeDeviceId { | |
431 | my $hostname = _getHostname(); | |
432 | ||
433 | my ($year, $month , $day, $hour, $min, $sec) = | |
434 | (localtime (time))[5, 4, 3, 2, 1, 0]; | |
435 | ||
436 | return sprintf "%s-%02d-%02d-%02d-%02d-%02d-%02d", | |
437 | $hostname, $year + 1900, $month + 1, $day, $hour, $min, $sec; | |
461 | 438 | } |
462 | 439 | |
463 | 440 | 1; |
514 | 491 | |
515 | 492 | Get the current agent status. |
516 | 493 | |
517 | =head2 getKnownTasks() | |
518 | ||
519 | Get all available tasks among hard-coded list, as a list of module / version | |
494 | =head2 getAvailableTasks() | |
495 | ||
496 | Get all available tasks found on the system, as a list of module / version | |
520 | 497 | pairs: |
521 | 498 | |
522 | 499 | %tasks = ( |
523 | 500 | 'FusionInventory::Agent::Task::Foo' => x, |
524 | 501 | 'FusionInventory::Agent::Task::Bar' => y, |
525 | 502 | ); |
526 | ||
527 | =head2 getAvailableTasks() | |
528 | ||
529 | Get all available tasks found on the system, as a list of module / version | |
530 | pairs: | |
531 | ||
532 | %tasks = ( | |
533 | 'FusionInventory::Agent::Task::Foo' => x, | |
534 | 'FusionInventory::Agent::Task::Bar' => y, | |
535 | ); |
0 | GeoIP-1.4.8_1 Find the country that any IP address or hostname originates | |
1 | ImageMagick-6.7.0.10_1 Image processing tools | |
2 | ORBit2-2.14.19 High-performance CORBA ORB with support for the C language | |
3 | Ocsinventory-Agent-1.1.2.1_1,1 Keep track of the computers configuration and software | |
4 | Ocsinventory-Agent-2.0,1 Keep track of the computers configuration and software | |
5 | OpenEXR-1.6.1_3 A high dynamic-range (HDR) image file format | |
6 | a2ps-a4-4.13b_4 Formats an ascii file for printing on a postscript printer | |
7 | aalib-1.4.r5_6 An ascii art library | |
8 | acidrip-0.14_8 GTK2::Perl wrapper for MPlayer and MEncoder for ripping DVD | |
9 | acroread8-8.1.7_3 Adobe Reader for view, print, and search PDF documents (ENU | |
10 | acroreadwrapper-0.0.20110920 Wrapper script for Adobe Reader | |
11 | alsa-lib-1.0.23 ALSA compatibility library | |
12 | ap22-mod_perl2-2.0.5_1,3 Embeds a Perl interpreter in the Apache2 server | |
13 | apache-2.2.19 Version 2.2.x of Apache web server with prefork MPM. | |
14 | apache-ant-1.8.2 Java- and XML-based build tool, conceptually similar to mak | |
15 | appres-1.0.3 Program to list application's resources | |
16 | apr-ipv6-devrandom-gdbm-db42-1.4.5.1.3.12 Apache Portability Library | |
17 | aspell-0.60.6.1 Spelling checker with better suggestion logic than ispell | |
18 | atk-2.0.1 A GNOME accessibility toolkit (ATK) | |
19 | atkmm-2.22.5 C++ wrapper for ATK API library | |
20 | attica-0.2.80,1 Collaboration Services API library | |
21 | atunes-2.0.1 A full-featured audio player and manager developed in Java | |
22 | audacity-1.2.4b_9 Audacity is a GUI editor for digital audio waveforms | |
23 | autoconf-2.13.000227_6 Automatically configure source code on many Un*x platforms | |
24 | autoconf-2.68 Automatically configure source code on many Un*x platforms | |
25 | autoconf-wrapper-20101119 Wrapper script for GNU autoconf | |
26 | automake-1.11.1 GNU Standards-compliant Makefile generator (1.11) | |
27 | automake-1.4.6_6 GNU Standards-compliant Makefile generator (1.4) | |
28 | automake-wrapper-20101119 Wrapper script for GNU automake | |
29 | automoc4-0.9.88_1 Automatic moc for Qt 4 packages | |
30 | avahi-app-0.6.29 Service discovery on a local network | |
31 | b43-fwcutter-012 Extracts firmware for Broadcom Wireless adapters | |
32 | babl-0.1.4 Dynamic pixel format conversion library | |
33 | bash-4.1.11 The GNU Project's Bourne Again SHell |
0 | lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1 | |
1 | inet 127.0.0.1 netmask ff000000 | |
2 | e1000g0: flags=1004843<UP,BROADCAST,RUNNING,MULTICAST,DHCP,IPv4> mtu 1500 index 2 | |
3 | inet 192.168.0.41 netmask ffffff00 broadcast 192.168.0.255 | |
4 | ether 8:0:27:fc:ad:56 | |
5 | lo0: flags=2002000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv6,VIRTUAL> mtu 8252 index 1 | |
6 | inet6 ::1/128 | |
7 | e1000g0: flags=2000841<UP,RUNNING,MULTICAST,IPv6> mtu 1480 index 2 | |
8 | inet6 fe80::a00:27ff:fefc:ad56/10 | |
9 | ether 8:0:27:fc:ad:56 | |
10 | e1000g0:1: flags=2080841<UP,RUNNING,MULTICAST,ADDRCONF,IPv6> mtu 1480 index 2 | |
11 | inet6 2a01:e35:8ad7:48d0:a00:27ff:fefc:ad56/64 |
0 | Routing tables | |
1 | ||
2 | Internet: | |
3 | Destination Gateway Flags Refs Use Netif Expire | |
4 | default 192.168.0.254 UGSc 10 2 en0 | |
5 | 127 127.0.0.1 UCS 0 0 lo0 | |
6 | 127.0.0.1 127.0.0.1 UH 10 8841 lo0 | |
7 | 169.254 link#4 UCS 0 0 en0 | |
8 | 192.168.0 link#4 UCS 1 0 en0 | |
9 | 192.168.0.27 127.0.0.1 UHS 0 13 lo0 | |
10 | 192.168.0.254 f4:ca:e5:42:38:37 UHLW 8 21 en0 1001 |
Binary diff not shown
Binary diff not shown
Binary diff not shown
Binary diff not shown
31 | 31 | # exclude linked modules |
32 | 32 | my @files = grep { filter($_) } all_pm_files('lib'); |
33 | 33 | |
34 | eval { require FusionInventory::Agent::SNMP; }; | |
35 | if ($EVAL_ERROR) { | |
36 | @files = grep { ! /SNMP/ } @files; | |
37 | } | |
38 | ||
39 | 34 | all_pm_files_ok(@files); |
0 | #!/usr/bin/perl | |
1 | ||
2 | use strict; | |
3 | use warnings; | |
4 | ||
5 | use English qw(-no_match_vars); | |
6 | use Test::More; | |
7 | use Test::Exception; | |
8 | ||
9 | use FusionInventory::Agent::XML::Response; | |
10 | ||
11 | eval { require FusionInventory::Agent::SNMP; }; | |
12 | ||
13 | if ($EVAL_ERROR) { | |
14 | my $msg = 'Unable to load FusionInventory::Agent::SNMP'; | |
15 | plan(skip_all => $msg); | |
16 | } | |
17 | ||
18 | plan tests => 9; | |
19 | ||
20 | my $snmp; | |
21 | throws_ok { | |
22 | $snmp = FusionInventory::Agent::SNMP->new(); | |
23 | } qr/^no hostname parameter/, | |
24 | 'instanciation: no hostname parameter'; | |
25 | ||
26 | throws_ok { | |
27 | $snmp = FusionInventory::Agent::SNMP->new( | |
28 | hostname => 'localhost', | |
29 | version => 'foo' | |
30 | ); | |
31 | } qr/^invalid SNMP version/, | |
32 | 'instanciation: invalid version parameter'; | |
33 | ||
34 | throws_ok { | |
35 | $snmp = FusionInventory::Agent::SNMP->new( | |
36 | hostname => 'localhost', | |
37 | version => 5 | |
38 | ); | |
39 | } qr/^invalid SNMP version/, | |
40 | 'instanciation: invalid version parameter'; | |
41 | ||
42 | throws_ok { | |
43 | $snmp = FusionInventory::Agent::SNMP->new( | |
44 | hostname => 'localhost', | |
45 | version => 1 | |
46 | ); | |
47 | } qr/[Cc]ommunity (is )?not defined/, | |
48 | 'instanciation: undefined community'; | |
49 | ||
50 | lives_ok { | |
51 | $snmp = FusionInventory::Agent::SNMP->new( | |
52 | version => 1, | |
53 | community => 'public', | |
54 | hostname => 'localhost' | |
55 | ); | |
56 | } 'instanciation: OK'; | |
57 | ||
58 | ok( | |
59 | !defined $snmp->get(), | |
60 | 'no OID' | |
61 | ); | |
62 | ||
63 | ok( | |
64 | !defined $snmp->walk(), | |
65 | 'no first OID' | |
66 | ); | |
67 | ||
68 | SKIP: { | |
69 | skip 'live SNMP test disabled', 2 unless $ENV{TEST_LIVE_SNMP}; | |
70 | ||
71 | is( | |
72 | $snmp->get('1.3.6.1.2.1.1.9.1.3.3'), | |
73 | 'The SNMP Management Architecture MIB.', | |
74 | 'simple value query' | |
75 | ); | |
76 | ||
77 | is_deeply( | |
78 | $snmp->walk('1.3.6.1.2.1.1.9.1.3'), | |
79 | { | |
80 | '1.3.6.1.2.1.1.9.1.3.1' => 'The MIB for Message Processing and Dispatching.', | |
81 | '1.3.6.1.2.1.1.9.1.3.2' => 'The MIB for Message Processing and Dispatching.', | |
82 | '1.3.6.1.2.1.1.9.1.3.3' => 'The SNMP Management Architecture MIB.', | |
83 | '1.3.6.1.2.1.1.9.1.3.4' => 'The MIB module for SNMPv2 entities', | |
84 | '1.3.6.1.2.1.1.9.1.3.5' => 'The MIB module for managing TCP implementations', | |
85 | '1.3.6.1.2.1.1.9.1.3.6' => 'The MIB module for managing IP and ICMP implementations', | |
86 | '1.3.6.1.2.1.1.9.1.3.7' => 'The MIB module for managing UDP implementations', | |
87 | '1.3.6.1.2.1.1.9.1.3.8' => 'View-based Access Control Model for SNMP.' | |
88 | }, | |
89 | 'multiple value query' | |
90 | ); | |
91 | } |
10 | 10 | |
11 | 11 | plan tests => 8; |
12 | 12 | |
13 | my %before = FusionInventory::Agent->getAvailableTasks(); | |
13 | my $agent = FusionInventory::Agent->new(); | |
14 | ||
15 | my %before = $agent->getAvailableTasks(); | |
14 | 16 | my $tmpdir = tempdir(CLEANUP => $ENV{TEST_DEBUG} ? 0 : 1); |
15 | 17 | my $tasks; |
16 | 18 | |
22 | 24 | $tasks = get_new_tasks("$tmpdir/1"); |
23 | 25 | is_deeply ( |
24 | 26 | $tasks, |
25 | { 'FusionInventory::Agent::Task::Test1' => 42 }, | |
27 | { 'Test1' => 42 }, | |
26 | 28 | "single task" |
27 | 29 | ); |
28 | 30 | |
40 | 42 | is_deeply ( |
41 | 43 | $tasks, |
42 | 44 | { |
43 | 'FusionInventory::Agent::Task::Test2a' => 42, | |
44 | 'FusionInventory::Agent::Task::Test2b' => 42 | |
45 | 'Test2a' => 42, | |
46 | 'Test2b' => 42 | |
45 | 47 | }, |
46 | 48 | "multiple tasks, single root" |
47 | 49 | ); |
60 | 62 | is_deeply ( |
61 | 63 | $tasks, |
62 | 64 | { |
63 | 'FusionInventory::Agent::Task::Test3a' => 42, | |
64 | 'FusionInventory::Agent::Task::Test3b' => 42 | |
65 | 'Test3a' => 42, | |
66 | 'Test3b' => 42 | |
65 | 67 | }, |
66 | 68 | "multiple tasks, multiple roots" |
67 | 69 | ); |
80 | 82 | is_deeply ( |
81 | 83 | $tasks, |
82 | 84 | { |
83 | 'FusionInventory::Agent::Task::Test4' => 42, | |
85 | 'Test4' => 42, | |
84 | 86 | }, |
85 | 87 | "single tasks, multiple versions, first found wins" |
86 | 88 | ); |
133 | 135 | |
134 | 136 | unshift @INC, @dirs; |
135 | 137 | |
136 | my %after = FusionInventory::Agent->getAvailableTasks(); | |
138 | my %after = $agent->getAvailableTasks(); | |
137 | 139 | |
138 | 140 | shift @INC foreach @dirs; |
139 | 141 |
13 | 13 | use FusionInventory::Agent::HTTP::Server; |
14 | 14 | use FusionInventory::Agent::Logger; |
15 | 15 | |
16 | plan tests => 5; | |
16 | plan tests => 7; | |
17 | 17 | |
18 | 18 | my $logger = FusionInventory::Agent::Logger->new( |
19 | 19 | backends => [ 'Test' ] |
33 | 33 | ); |
34 | 34 | } 'instanciation with default values: ok'; |
35 | 35 | |
36 | my $client = LWP::UserAgent->new(); | |
36 | my $client = LWP::UserAgent->new(timeout => 2); | |
37 | 37 | |
38 | 38 | ok( |
39 | 39 | $client->get('http://localhost:62354')->is_success(), |
40 | 40 | 'server listening on default port' |
41 | 41 | ); |
42 | ||
43 | $server->terminate(); | |
42 | 44 | |
43 | 45 | lives_ok { |
44 | 46 | $server = FusionInventory::Agent::HTTP::Server->new( |
49 | 51 | htmldir => 'share/html' |
50 | 52 | ); |
51 | 53 | } 'instanciation with specific port: ok'; |
54 | sleep 1; | |
52 | 55 | |
53 | 56 | ok( |
54 | 57 | !$client->get('http://localhost:62354')->is_success(), |
59 | 62 | $client->get('http://localhost:8080')->is_success(), |
60 | 63 | 'server listening on specific port' |
61 | 64 | ); |
65 | ||
66 | # fork a child process, as when running in server mode | |
67 | if (my $pid = fork()) { | |
68 | # parent | |
69 | waitpid($pid, 0); | |
70 | } else { | |
71 | # child | |
72 | exit(0); | |
73 | } | |
74 | ||
75 | ok( | |
76 | $client->get('http://localhost:8080')->is_success(), | |
77 | 'server still listening after child process exit' | |
78 | ); | |
79 | ||
80 | # fork a child process, and raise ALRM from it, as when a timeout is reached | |
81 | if (my $pid = fork()) { | |
82 | # parent | |
83 | waitpid($pid, 0); | |
84 | } else { | |
85 | # child | |
86 | alarm 1; | |
87 | exit(0); | |
88 | } | |
89 | ||
90 | ok( | |
91 | $client->get('http://localhost:8080')->is_success(), | |
92 | 'server still listening after child process raised ALRM' | |
93 | ); | |
94 | ||
95 | ||
96 | $server->terminate(); |
0 | #!/usr/bin/perl | |
1 | ||
2 | use strict; | |
3 | use warnings; | |
4 | ||
5 | use Test::More; | |
6 | ||
7 | use FusionInventory::Agent::Task::Inventory::Input::BSD::Softwares; | |
8 | ||
9 | my %pkg_info_tests = ( | |
10 | 'sample1' => [ | |
11 | { | |
12 | 'NAME' => 'GeoIP', | |
13 | 'DESCRIPTION' => 'Find the country that any IP address or hostname originates', | |
14 | 'VERSION' => '1.4.8_1' | |
15 | }, | |
16 | { | |
17 | 'NAME' => 'ImageMagick', | |
18 | 'DESCRIPTION' => 'Image processing tools', | |
19 | 'VERSION' => '6.7.0.10_1' | |
20 | }, | |
21 | { | |
22 | 'NAME' => 'ORBit2', | |
23 | 'DESCRIPTION' => 'High-performance CORBA ORB with support for the C language', | |
24 | 'VERSION' => '2.14.19' | |
25 | }, | |
26 | { | |
27 | 'NAME' => 'Ocsinventory-Agent', | |
28 | 'DESCRIPTION' => 'Keep track of the computers configuration and software', | |
29 | 'VERSION' => '1.1.2.1_1,1' | |
30 | }, | |
31 | { | |
32 | 'NAME' => 'Ocsinventory-Agent', | |
33 | 'DESCRIPTION' => 'Keep track of the computers configuration and software', | |
34 | 'VERSION' => '2.0,1' | |
35 | }, | |
36 | { | |
37 | 'NAME' => 'OpenEXR', | |
38 | 'DESCRIPTION' => 'A high dynamic-range (HDR) image file format', | |
39 | 'VERSION' => '1.6.1_3' | |
40 | }, | |
41 | { | |
42 | 'NAME' => 'a2ps-a4', | |
43 | 'DESCRIPTION' => 'Formats an ascii file for printing on a postscript printer', | |
44 | 'VERSION' => '4.13b_4' | |
45 | }, | |
46 | { | |
47 | 'NAME' => 'aalib', | |
48 | 'DESCRIPTION' => 'An ascii art library', | |
49 | 'VERSION' => '1.4.r5_6' | |
50 | }, | |
51 | { | |
52 | 'NAME' => 'acidrip', | |
53 | 'DESCRIPTION' => 'GTK2::Perl wrapper for MPlayer and MEncoder for ripping DVD', | |
54 | 'VERSION' => '0.14_8' | |
55 | }, | |
56 | { | |
57 | 'NAME' => 'acroread8', | |
58 | 'DESCRIPTION' => 'Adobe Reader for view, print, and search PDF documents (ENU', | |
59 | 'VERSION' => '8.1.7_3' | |
60 | }, | |
61 | { | |
62 | 'NAME' => 'acroreadwrapper', | |
63 | 'DESCRIPTION' => 'Wrapper script for Adobe Reader', | |
64 | 'VERSION' => '0.0.20110920' | |
65 | }, | |
66 | { | |
67 | 'NAME' => 'alsa-lib', | |
68 | 'DESCRIPTION' => 'ALSA compatibility library', | |
69 | 'VERSION' => '1.0.23' | |
70 | }, | |
71 | { | |
72 | 'NAME' => 'ap22-mod_perl2', | |
73 | 'DESCRIPTION' => 'Embeds a Perl interpreter in the Apache2 server', | |
74 | 'VERSION' => '2.0.5_1,3' | |
75 | }, | |
76 | { | |
77 | 'NAME' => 'apache', | |
78 | 'DESCRIPTION' => 'Version 2.2.x of Apache web server with prefork MPM.', | |
79 | 'VERSION' => '2.2.19' | |
80 | }, | |
81 | { | |
82 | 'NAME' => 'apache-ant', | |
83 | 'DESCRIPTION' => 'Java- and XML-based build tool, conceptually similar to mak', | |
84 | 'VERSION' => '1.8.2' | |
85 | }, | |
86 | { | |
87 | 'NAME' => 'appres', | |
88 | 'DESCRIPTION' => 'Program to list application\'s resources', | |
89 | 'VERSION' => '1.0.3' | |
90 | }, | |
91 | { | |
92 | 'NAME' => 'apr-ipv6-devrandom-gdbm-db42', | |
93 | 'DESCRIPTION' => 'Apache Portability Library', | |
94 | 'VERSION' => '1.4.5.1.3.12' | |
95 | }, | |
96 | { | |
97 | 'NAME' => 'aspell', | |
98 | 'DESCRIPTION' => 'Spelling checker with better suggestion logic than ispell', | |
99 | 'VERSION' => '0.60.6.1' | |
100 | }, | |
101 | { | |
102 | 'NAME' => 'atk', | |
103 | 'DESCRIPTION' => 'A GNOME accessibility toolkit (ATK)', | |
104 | 'VERSION' => '2.0.1' | |
105 | }, | |
106 | { | |
107 | 'NAME' => 'atkmm', | |
108 | 'DESCRIPTION' => 'C++ wrapper for ATK API library', | |
109 | 'VERSION' => '2.22.5' | |
110 | }, | |
111 | { | |
112 | 'NAME' => 'attica', | |
113 | 'DESCRIPTION' => 'Collaboration Services API library', | |
114 | 'VERSION' => '0.2.80,1' | |
115 | }, | |
116 | { | |
117 | 'NAME' => 'atunes', | |
118 | 'DESCRIPTION' => 'A full-featured audio player and manager developed in Java', | |
119 | 'VERSION' => '2.0.1' | |
120 | }, | |
121 | { | |
122 | 'NAME' => 'audacity', | |
123 | 'DESCRIPTION' => 'Audacity is a GUI editor for digital audio waveforms', | |
124 | 'VERSION' => '1.2.4b_9' | |
125 | }, | |
126 | { | |
127 | 'NAME' => 'autoconf', | |
128 | 'DESCRIPTION' => 'Automatically configure source code on many Un*x platforms ', | |
129 | 'VERSION' => '2.13.000227_6' | |
130 | }, | |
131 | { | |
132 | 'NAME' => 'autoconf', | |
133 | 'DESCRIPTION' => 'Automatically configure source code on many Un*x platforms ', | |
134 | 'VERSION' => '2.68' | |
135 | }, | |
136 | { | |
137 | 'NAME' => 'autoconf-wrapper', | |
138 | 'DESCRIPTION' => 'Wrapper script for GNU autoconf', | |
139 | 'VERSION' => '20101119' | |
140 | }, | |
141 | { | |
142 | 'NAME' => 'automake', | |
143 | 'DESCRIPTION' => 'GNU Standards-compliant Makefile generator (1.11)', | |
144 | 'VERSION' => '1.11.1' | |
145 | }, | |
146 | { | |
147 | 'NAME' => 'automake', | |
148 | 'DESCRIPTION' => 'GNU Standards-compliant Makefile generator (1.4)', | |
149 | 'VERSION' => '1.4.6_6' | |
150 | }, | |
151 | { | |
152 | 'NAME' => 'automake-wrapper', | |
153 | 'DESCRIPTION' => 'Wrapper script for GNU automake', | |
154 | 'VERSION' => '20101119' | |
155 | }, | |
156 | { | |
157 | 'NAME' => 'automoc4', | |
158 | 'DESCRIPTION' => 'Automatic moc for Qt 4 packages', | |
159 | 'VERSION' => '0.9.88_1' | |
160 | }, | |
161 | { | |
162 | 'NAME' => 'avahi-app', | |
163 | 'DESCRIPTION' => 'Service discovery on a local network', | |
164 | 'VERSION' => '0.6.29' | |
165 | }, | |
166 | { | |
167 | 'NAME' => 'b43-fwcutter', | |
168 | 'DESCRIPTION' => 'Extracts firmware for Broadcom Wireless adapters', | |
169 | 'VERSION' => '012' | |
170 | }, | |
171 | { | |
172 | 'NAME' => 'babl', | |
173 | 'DESCRIPTION' => 'Dynamic pixel format conversion library', | |
174 | 'VERSION' => '0.1.4' | |
175 | }, | |
176 | { | |
177 | 'NAME' => 'bash', | |
178 | 'DESCRIPTION' => 'The GNU Project\'s Bourne Again SHell', | |
179 | 'VERSION' => '4.1.11' | |
180 | } | |
181 | ] | |
182 | ); | |
183 | ||
184 | plan tests => scalar keys %pkg_info_tests; | |
185 | ||
186 | use Data::Dumper; | |
187 | foreach my $test (keys %pkg_info_tests) { | |
188 | my $file = "resources/bsd/pkg_info/$test"; | |
189 | my $results = FusionInventory::Agent::Task::Inventory::Input::BSD::Softwares::_getPackagesListFromPkgInfo(file => $file); | |
190 | is_deeply($results, $pkg_info_tests{$test}, $test) or print Dumper($results); | |
191 | } |
0 | #!/usr/bin/perl | |
1 | ||
2 | use strict; | |
3 | use warnings; | |
4 | ||
5 | use Test::More; | |
6 | ||
7 | use FusionInventory::Agent::Task::Inventory::Input::Linux::Networks; | |
8 | ||
9 | my %ifconfig_tests = ( | |
10 | 'dell-xt2' => [ | |
11 | { | |
12 | MACADDR => 'A4:BA:DB:A5:F5:FA', | |
13 | STATUS => 'Up', | |
14 | TYPE => 'Ethernet', | |
15 | DESCRIPTION => 'eth0', | |
16 | IPMASK => '255.255.255.0', | |
17 | IPADDRESS => '192.168.0.5', | |
18 | IPADDRESS6 => 'fe80::a6ba:dbff:fea5:f5fa/64' | |
19 | }, | |
20 | { | |
21 | DESCRIPTION => 'lo', | |
22 | STATUS => 'Up', | |
23 | TYPE => 'Local', | |
24 | IPMASK => '255.0.0.0', | |
25 | IPADDRESS => '127.0.0.1', | |
26 | IPADDRESS6 => '::1/128', | |
27 | }, | |
28 | { | |
29 | MACADDR => '4E:8C:81:ED:9B:35', | |
30 | DESCRIPTION => 'pan0', | |
31 | STATUS => 'Down', | |
32 | TYPE => 'Ethernet', | |
33 | }, | |
34 | { | |
35 | DESCRIPTION => 'sit0', | |
36 | STATUS => 'Down', | |
37 | TYPE => 'IPv6-in-IPv4', | |
38 | }, | |
39 | { | |
40 | MACADDR => '00:24:D6:6F:81:3A', | |
41 | STATUS => 'Up', | |
42 | TYPE => 'Ethernet', | |
43 | DESCRIPTION => 'wlan0', | |
44 | IPMASK => '255.255.192.0', | |
45 | IPADDRESS => '78.251.91.204', | |
46 | IPADDRESS6 => 'fe80::224:d6ff:fe6f:813a/64' | |
47 | } | |
48 | ], | |
49 | 'linux-bonding' => [ | |
50 | { | |
51 | IPMASK => '255.255.255.0', | |
52 | MACADDR => '00:50:56:AD:00:0E', | |
53 | DESCRIPTION => 'bond0', | |
54 | STATUS => 'Up', | |
55 | TYPE => 'Ethernet', | |
56 | IPADDRESS6 => 'fe80::250:56ff:fead:e/64', | |
57 | IPADDRESS => '192.168.1.181' | |
58 | }, | |
59 | { | |
60 | MACADDR => '00:50:56:AD:00:0E', | |
61 | DESCRIPTION => 'eth0', | |
62 | STATUS => 'Up', | |
63 | TYPE => 'Ethernet' | |
64 | }, | |
65 | { | |
66 | IPMASK => '255.0.0.0', | |
67 | DESCRIPTION => 'lo', | |
68 | STATUS => 'Up', | |
69 | TYPE => 'Local', | |
70 | IPADDRESS6 => '::1/128', | |
71 | IPADDRESS => '127.0.0.1' | |
72 | } | |
73 | ], | |
74 | 'linux-rhel5.6' => [ | |
75 | { | |
76 | IPMASK => '255.255.252.0', | |
77 | MACADDR => '00:1E:68:2F:85:D8', | |
78 | DESCRIPTION => 'eth0', | |
79 | STATUS => 'Up', | |
80 | TYPE => 'Ethernet', | |
81 | IPADDRESS6 => 'fe80::21e:68ff:fe2f:85d8/64', | |
82 | IPADDRESS => '10.202.0.31' | |
83 | }, | |
84 | { | |
85 | IPMASK => '255.0.0.0', | |
86 | DESCRIPTION => 'lo', | |
87 | STATUS => 'Up', | |
88 | TYPE => 'Local', | |
89 | IPADDRESS6 => '::1/128', | |
90 | IPADDRESS => '127.0.0.1' | |
91 | }, | |
92 | { | |
93 | MACADDR => '00:1E:68:2F:85:D8', | |
94 | DESCRIPTION => 'peth0', | |
95 | STATUS => 'Up', | |
96 | TYPE => 'Ethernet', | |
97 | IPADDRESS6 => 'fe80::21e:68ff:fe2f:85d8/64' | |
98 | }, | |
99 | { | |
100 | MACADDR => 'FE:FF:FF:FF:FF:FF', | |
101 | DESCRIPTION => 'vif1.0', | |
102 | STATUS => 'Up', | |
103 | TYPE => 'Ethernet', | |
104 | IPADDRESS6 => 'fe80::fcff:ffff:feff:ffff/64' | |
105 | }, | |
106 | { | |
107 | MACADDR => 'FE:FF:FF:FF:FF:FF', | |
108 | DESCRIPTION => 'vif2.0', | |
109 | STATUS => 'Up', | |
110 | TYPE => 'Ethernet', | |
111 | IPADDRESS6 => 'fe80::fcff:ffff:feff:ffff/64' | |
112 | }, | |
113 | { | |
114 | MACADDR => 'FE:FF:FF:FF:FF:FF', | |
115 | DESCRIPTION => 'vif3.0', | |
116 | STATUS => 'Up', | |
117 | TYPE => 'Ethernet', | |
118 | IPADDRESS6 => 'fe80::fcff:ffff:feff:ffff/64' | |
119 | }, | |
120 | { | |
121 | MACADDR => 'FE:FF:FF:FF:FF:FF', | |
122 | DESCRIPTION => 'vif4.0', | |
123 | STATUS => 'Up', | |
124 | TYPE => 'Ethernet', | |
125 | IPADDRESS6 => 'fe80::fcff:ffff:feff:ffff/64' | |
126 | }, | |
127 | { | |
128 | MACADDR => 'FE:FF:FF:FF:FF:FF', | |
129 | DESCRIPTION => 'vif5.0', | |
130 | STATUS => 'Up', | |
131 | TYPE => 'Ethernet', | |
132 | IPADDRESS6 => 'fe80::fcff:ffff:feff:ffff/64' | |
133 | }, | |
134 | { | |
135 | MACADDR => 'FE:FF:FF:FF:FF:FF', | |
136 | DESCRIPTION => 'vif6.0', | |
137 | STATUS => 'Up', | |
138 | TYPE => 'Ethernet', | |
139 | IPADDRESS6 => 'fe80::fcff:ffff:feff:ffff/64' | |
140 | } | |
141 | ] | |
142 | ); | |
143 | ||
144 | my %ipaddrshow_tests = ( | |
145 | 'ip_addr-1' => [ | |
146 | { | |
147 | IPSUBNET => '127.0.0.0', | |
148 | IPMASK => '255.0.0.0', | |
149 | STATUS => 'Up', | |
150 | DESCRIPTION => 'lo', | |
151 | IPADDRESS6 => '::1', | |
152 | IPADDRESS => '127.0.0.1' | |
153 | }, | |
154 | { | |
155 | IPSUBNET => '192.168.0.0', | |
156 | IPMASK => '255.255.255.0', | |
157 | MACADDR => '00:23:18:91:db:8d', | |
158 | STATUS => 'Up', | |
159 | DESCRIPTION => 'eth0', | |
160 | IPADDRESS6 => 'fe80::223:18ff:fe91:db8d', | |
161 | IPADDRESS => '192.168.0.10' | |
162 | }, | |
163 | { | |
164 | STATUS => 'Up', | |
165 | DESCRIPTION => 'tun0' | |
166 | }, | |
167 | { | |
168 | STATUS => 'Up', | |
169 | DESCRIPTION => 'tun1' | |
170 | }, | |
171 | { | |
172 | MACADDR => 'e8:39:df:3f:7d:ef', | |
173 | STATUS => 'Down', | |
174 | DESCRIPTION => 'wlan0' | |
175 | } | |
176 | ], | |
177 | 'ip_addr-2' => [ | |
178 | { | |
179 | IPSUBNET => '127.0.0.0', | |
180 | IPMASK => '255.0.0.0', | |
181 | STATUS => 'Up', | |
182 | DESCRIPTION => 'lo', | |
183 | IPADDRESS6 => '::1', | |
184 | IPADDRESS => '127.0.0.1' | |
185 | }, | |
186 | { | |
187 | IPSUBNET => '172.16.0.0', | |
188 | IPMASK => '255.255.128.0', | |
189 | MACADDR => '0f:0f:0f:0f:0f:0f', | |
190 | STATUS => 'Up', | |
191 | DESCRIPTION => 'eth0', | |
192 | IPADDRESS6 => 'fe80::201:29ff:fed1:feb4', | |
193 | IPADDRESS => '172.16.0.201' | |
194 | }, | |
195 | { | |
196 | STATUS => 'Down', | |
197 | DESCRIPTION => 'eql' | |
198 | }, | |
199 | { | |
200 | STATUS => 'Down', | |
201 | DESCRIPTION => 'sit0' | |
202 | } | |
203 | ] | |
204 | ); | |
205 | ||
206 | plan tests => | |
207 | int (keys %ifconfig_tests) + | |
208 | int (keys %ipaddrshow_tests); | |
209 | ||
210 | foreach my $test (keys %ifconfig_tests) { | |
211 | my $file = "resources/generic/ifconfig/$test"; | |
212 | my @results = FusionInventory::Agent::Task::Inventory::Input::Linux::Networks::_parseIfconfig(file => $file); | |
213 | is_deeply(\@results, $ifconfig_tests{$test}, $test); | |
214 | } | |
215 | ||
216 | foreach my $test (keys %ipaddrshow_tests) { | |
217 | my $file = "resources/linux/ip/$test"; | |
218 | my @results = FusionInventory::Agent::Task::Inventory::Input::Linux::Networks::_parseIpAddrShow(file => $file); | |
219 | is_deeply(\@results, $ipaddrshow_tests{$test}, $test); | |
220 | } |
10 | 10 | '10.4-powerpc' => { |
11 | 11 | MONITORS => [ |
12 | 12 | { |
13 | SERIAL => '', | |
14 | MANUFACTURER => '', | |
15 | 13 | DESCRIPTION => 'ASUS VH222', |
16 | 14 | CAPTION => 'ASUS VH222' |
17 | 15 | } |
30 | 28 | { |
31 | 29 | MONITORS => [ |
32 | 30 | { |
33 | SERIAL => '', | |
34 | MANUFACTURER => '', | |
35 | 31 | DESCRIPTION => 'ASUS VH222', |
36 | 32 | CAPTION => 'ASUS VH222' |
37 | 33 | } |
49 | 45 | '10.6-intel' => { |
50 | 46 | MONITORS => [ |
51 | 47 | { |
52 | SERIAL => '', | |
53 | MANUFACTURER => '', | |
54 | 48 | DESCRIPTION => 'iMac', |
55 | 49 | CAPTION => 'iMac' |
56 | 50 | } |
68 | 62 | '10.6.6-intel' => { |
69 | 63 | MONITORS => [ |
70 | 64 | { |
71 | SERIAL => '', | |
72 | MANUFACTURER => '', | |
73 | 65 | DESCRIPTION => 'Color LCD', |
74 | 66 | CAPTION => 'Color LCD' |
75 | 67 | } |
78 | 78 | IPADDRESS => '192.168.20.1' |
79 | 79 | } |
80 | 80 | ], |
81 | 'opensolaris' => [ | |
82 | { | |
83 | 'IPSUBNET' => '127.0.0.0', | |
84 | 'IPGATEWAY' => undef, | |
85 | 'IPMASK' => '255.0.0.0', | |
86 | 'DESCRIPTION' => 'lo0', | |
87 | 'STATUS' => 'Up', | |
88 | 'SPEED' => undef, | |
89 | 'IPADDRESS' => '127.0.0.1' | |
90 | }, | |
91 | { | |
92 | 'IPGATEWAY' => undef, | |
93 | 'IPMASK' => '255.255.255.0', | |
94 | 'MACADDR' => '08:00:27:fc:ad:56', | |
95 | 'STATUS' => 'Up', | |
96 | 'SPEED' => undef, | |
97 | 'IPSUBNET' => '192.168.0.0', | |
98 | 'DESCRIPTION' => 'e1000g0', | |
99 | 'IPADDRESS' => '192.168.0.41' | |
100 | }, | |
101 | { | |
102 | 'IPSUBNET' => undef, | |
103 | 'DESCRIPTION' => 'lo0', | |
104 | 'STATUS' => 'Up', | |
105 | 'SPEED' => undef | |
106 | }, | |
107 | { | |
108 | 'IPSUBNET' => undef, | |
109 | 'MACADDR' => '08:00:27:fc:ad:56', | |
110 | 'DESCRIPTION' => 'e1000g0', | |
111 | 'STATUS' => 'Up', | |
112 | 'SPEED' => undef | |
113 | }, | |
114 | { | |
115 | 'IPSUBNET' => undef, | |
116 | 'DESCRIPTION' => 'e1000g0:1', | |
117 | 'STATUS' => 'Up', | |
118 | 'SPEED' => undef | |
119 | } | |
120 | ] | |
81 | 121 | |
82 | 122 | ); |
83 | 123 | |
84 | 124 | plan tests => |
85 | 125 | int (keys %ifconfig_tests); |
86 | 126 | |
127 | use Data::Dumper; | |
87 | 128 | foreach my $test (keys %ifconfig_tests) { |
88 | 129 | my $file = "resources/generic/ifconfig/$test"; |
89 | 130 | my @results = FusionInventory::Agent::Task::Inventory::Input::Solaris::Networks::_getInterfaces(file => $file); |
90 | is_deeply(\@results, $ifconfig_tests{$test}, $test); | |
131 | is_deeply(\@results, $ifconfig_tests{$test}, $test) or print Dumper(\@results); | |
91 | 132 | } |
92 | 133 |
535 | 535 | 'dell-xt2' => 'DFW1W11002SE002B3117' |
536 | 536 | ); |
537 | 537 | |
538 | my %ifconfig_tests = ( | |
539 | 'dell-xt2' => [ | |
540 | { | |
541 | MACADDR => 'A4:BA:DB:A5:F5:FA', | |
542 | STATUS => 'Up', | |
543 | TYPE => 'Ethernet', | |
544 | DESCRIPTION => 'eth0', | |
545 | IPMASK => '255.255.255.0', | |
546 | IPADDRESS => '192.168.0.5', | |
547 | IPADDRESS6 => 'fe80::a6ba:dbff:fea5:f5fa/64' | |
548 | }, | |
549 | { | |
550 | DESCRIPTION => 'lo', | |
551 | STATUS => 'Up', | |
552 | TYPE => 'Local', | |
553 | IPMASK => '255.0.0.0', | |
554 | IPADDRESS => '127.0.0.1', | |
555 | IPADDRESS6 => '::1/128', | |
556 | }, | |
557 | { | |
558 | MACADDR => '4E:8C:81:ED:9B:35', | |
559 | DESCRIPTION => 'pan0', | |
560 | STATUS => 'Down', | |
561 | TYPE => 'Ethernet', | |
562 | }, | |
563 | { | |
564 | DESCRIPTION => 'sit0', | |
565 | STATUS => 'Down', | |
566 | TYPE => 'IPv6-in-IPv4', | |
567 | }, | |
568 | { | |
569 | MACADDR => '00:24:D6:6F:81:3A', | |
570 | STATUS => 'Up', | |
571 | TYPE => 'Ethernet', | |
572 | DESCRIPTION => 'wlan0', | |
573 | IPMASK => '255.255.192.0', | |
574 | IPADDRESS => '78.251.91.204', | |
575 | IPADDRESS6 => 'fe80::224:d6ff:fe6f:813a/64' | |
576 | } | |
577 | ], | |
578 | 'linux-bonding' => [ | |
579 | { | |
580 | IPMASK => '255.255.255.0', | |
581 | MACADDR => '00:50:56:AD:00:0E', | |
582 | DESCRIPTION => 'bond0', | |
583 | STATUS => 'Up', | |
584 | TYPE => 'Ethernet', | |
585 | IPADDRESS6 => 'fe80::250:56ff:fead:e/64', | |
586 | IPADDRESS => '192.168.1.181' | |
587 | }, | |
588 | { | |
589 | MACADDR => '00:50:56:AD:00:0E', | |
590 | DESCRIPTION => 'eth0', | |
591 | STATUS => 'Up', | |
592 | TYPE => 'Ethernet' | |
593 | }, | |
594 | { | |
595 | IPMASK => '255.0.0.0', | |
596 | DESCRIPTION => 'lo', | |
597 | STATUS => 'Up', | |
598 | TYPE => 'Local', | |
599 | IPADDRESS6 => '::1/128', | |
600 | IPADDRESS => '127.0.0.1' | |
601 | } | |
602 | ], | |
603 | 'linux-rhel5.6' => [ | |
604 | { | |
605 | IPMASK => '255.255.252.0', | |
606 | MACADDR => '00:1E:68:2F:85:D8', | |
607 | DESCRIPTION => 'eth0', | |
608 | STATUS => 'Up', | |
609 | TYPE => 'Ethernet', | |
610 | IPADDRESS6 => 'fe80::21e:68ff:fe2f:85d8/64', | |
611 | IPADDRESS => '10.202.0.31' | |
612 | }, | |
613 | { | |
614 | IPMASK => '255.0.0.0', | |
615 | DESCRIPTION => 'lo', | |
616 | STATUS => 'Up', | |
617 | TYPE => 'Local', | |
618 | IPADDRESS6 => '::1/128', | |
619 | IPADDRESS => '127.0.0.1' | |
620 | }, | |
621 | { | |
622 | MACADDR => '00:1E:68:2F:85:D8', | |
623 | DESCRIPTION => 'peth0', | |
624 | STATUS => 'Up', | |
625 | TYPE => 'Ethernet', | |
626 | IPADDRESS6 => 'fe80::21e:68ff:fe2f:85d8/64' | |
627 | }, | |
628 | { | |
629 | MACADDR => 'FE:FF:FF:FF:FF:FF', | |
630 | DESCRIPTION => 'vif1.0', | |
631 | STATUS => 'Up', | |
632 | TYPE => 'Ethernet', | |
633 | IPADDRESS6 => 'fe80::fcff:ffff:feff:ffff/64' | |
634 | }, | |
635 | { | |
636 | MACADDR => 'FE:FF:FF:FF:FF:FF', | |
637 | DESCRIPTION => 'vif2.0', | |
638 | STATUS => 'Up', | |
639 | TYPE => 'Ethernet', | |
640 | IPADDRESS6 => 'fe80::fcff:ffff:feff:ffff/64' | |
641 | }, | |
642 | { | |
643 | MACADDR => 'FE:FF:FF:FF:FF:FF', | |
644 | DESCRIPTION => 'vif3.0', | |
645 | STATUS => 'Up', | |
646 | TYPE => 'Ethernet', | |
647 | IPADDRESS6 => 'fe80::fcff:ffff:feff:ffff/64' | |
648 | }, | |
649 | { | |
650 | MACADDR => 'FE:FF:FF:FF:FF:FF', | |
651 | DESCRIPTION => 'vif4.0', | |
652 | STATUS => 'Up', | |
653 | TYPE => 'Ethernet', | |
654 | IPADDRESS6 => 'fe80::fcff:ffff:feff:ffff/64' | |
655 | }, | |
656 | { | |
657 | MACADDR => 'FE:FF:FF:FF:FF:FF', | |
658 | DESCRIPTION => 'vif5.0', | |
659 | STATUS => 'Up', | |
660 | TYPE => 'Ethernet', | |
661 | IPADDRESS6 => 'fe80::fcff:ffff:feff:ffff/64' | |
662 | }, | |
663 | { | |
664 | MACADDR => 'FE:FF:FF:FF:FF:FF', | |
665 | DESCRIPTION => 'vif6.0', | |
666 | STATUS => 'Up', | |
667 | TYPE => 'Ethernet', | |
668 | IPADDRESS6 => 'fe80::fcff:ffff:feff:ffff/64' | |
669 | } | |
670 | ] | |
671 | ); | |
672 | ||
673 | my %ipaddrshow_tests = ( | |
674 | 'ip_addr-1' => [ | |
675 | { | |
676 | IPSUBNET => '127.0.0.0', | |
677 | IPMASK => '255.0.0.0', | |
678 | STATUS => 'Up', | |
679 | DESCRIPTION => 'lo', | |
680 | IPADDRESS6 => '::1', | |
681 | IPADDRESS => '127.0.0.1' | |
682 | }, | |
683 | { | |
684 | IPSUBNET => '192.168.0.0', | |
685 | IPMASK => '255.255.255.0', | |
686 | MACADDR => '00:23:18:91:db:8d', | |
687 | STATUS => 'Up', | |
688 | DESCRIPTION => 'eth0', | |
689 | IPADDRESS6 => 'fe80::223:18ff:fe91:db8d', | |
690 | IPADDRESS => '192.168.0.10' | |
691 | }, | |
692 | { | |
693 | STATUS => 'Up', | |
694 | DESCRIPTION => 'tun0' | |
695 | }, | |
696 | { | |
697 | STATUS => 'Up', | |
698 | DESCRIPTION => 'tun1' | |
699 | }, | |
700 | { | |
701 | MACADDR => 'e8:39:df:3f:7d:ef', | |
702 | STATUS => 'Down', | |
703 | DESCRIPTION => 'wlan0' | |
704 | } | |
705 | ], | |
706 | 'ip_addr-2' => [ | |
707 | { | |
708 | IPSUBNET => '127.0.0.0', | |
709 | IPMASK => '255.0.0.0', | |
710 | STATUS => 'Up', | |
711 | DESCRIPTION => 'lo', | |
712 | IPADDRESS6 => '::1', | |
713 | IPADDRESS => '127.0.0.1' | |
714 | }, | |
715 | { | |
716 | IPSUBNET => '172.16.0.0', | |
717 | IPMASK => '255.255.128.0', | |
718 | MACADDR => '0f:0f:0f:0f:0f:0f', | |
719 | STATUS => 'Up', | |
720 | DESCRIPTION => 'eth0', | |
721 | IPADDRESS6 => 'fe80::201:29ff:fed1:feb4', | |
722 | IPADDRESS => '172.16.0.201' | |
723 | }, | |
724 | { | |
725 | STATUS => 'Down', | |
726 | DESCRIPTION => 'eql' | |
727 | }, | |
728 | { | |
729 | STATUS => 'Down', | |
730 | DESCRIPTION => 'sit0' | |
731 | } | |
732 | ] | |
733 | ); | |
734 | ||
538 | 735 | plan tests => |
539 | (scalar keys %udev_tests) + | |
736 | (scalar keys %udev_tests) + | |
540 | 737 | (scalar keys %cpuinfo_tests) + |
541 | (scalar keys %hal_tests) + | |
542 | (scalar keys %smartctl_tests); | |
738 | (scalar keys %hal_tests) + | |
739 | (scalar keys %smartctl_tests) + | |
740 | (scalar keys %ifconfig_tests) + | |
741 | (scalar keys %ipaddrshow_tests); | |
543 | 742 | |
544 | 743 | foreach my $test (keys %udev_tests) { |
545 | 744 | my $file = "resources/linux/udev/$test"; |
566 | 765 | my $result = getSerialnumber(file => $file); |
567 | 766 | is($result, $smartctl_tests{$test}, "$test smartctl parsing"); |
568 | 767 | } |
768 | ||
769 | foreach my $test (keys %ifconfig_tests) { | |
770 | my $file = "resources/generic/ifconfig/$test"; | |
771 | my @interfaces = getInterfacesFromIfconfig(file => $file); | |
772 | is_deeply(\@interfaces, $ifconfig_tests{$test}, $test); | |
773 | } | |
774 | ||
775 | foreach my $test (keys %ipaddrshow_tests) { | |
776 | my $file = "resources/linux/ip/$test"; | |
777 | my @interfaces = getInterfacesFromIp(file => $file); | |
778 | is_deeply(\@interfaces, $ipaddrshow_tests{$test}, $test); | |
779 | } |
18 | 18 | ); |
19 | 19 | |
20 | 20 | my @hex2canonical_tests = ( |
21 | [ 'ffffffff', '255.255.255.255' ], | |
22 | [ '7f7f7f7f', '127.127.127.127' ] | |
21 | [ 'ffffffff', '255.255.255.255' ], | |
22 | [ '0xffffffff', '255.255.255.255' ], | |
23 | [ '7f7f7f7f', '127.127.127.127' ], | |
24 | [ '0x7f7f7f7f', '127.127.127.127' ] | |
23 | 25 | ); |
24 | 26 | |
25 | 27 | my @alt2canonical_tests = ( |
2348 | 2348 | linux1 => { |
2349 | 2349 | '0.0.0.0' => '192.168.0.254', |
2350 | 2350 | '192.168.0.0' => '0.0.0.0' |
2351 | }, | |
2352 | macosx1 => { | |
2353 | '192.168.0.254' => 'f4:ca:e5:42:38:37', | |
2354 | '127.0.0.1' => '127.0.0.1', | |
2355 | '192.168.0.27' => '127.0.0.1', | |
2356 | 'default' => '192.168.0.254' | |
2351 | 2357 | } |
2352 | 2358 | ); |
2353 | 2359 |