Skip to content

Commit

Permalink
feat: Update AIX bios support
Browse files Browse the repository at this point in the history
  • Loading branch information
g-bougard committed Sep 4, 2023
1 parent 3acd88f commit 6c81643
Show file tree
Hide file tree
Showing 5 changed files with 287 additions and 16 deletions.
1 change: 1 addition & 0 deletions Changes
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ inventory:
* Update RustDesk remote_mgmt support starting from RustDesk v1.2.2
* Fix Microsoft Defender Antivirus support on MacOSX
* fix #458: Add Microsoft Defender Antivirus support on Linux, thanks to @j-ldes
* Refactoring & enhanced Aix bios inventory to use lsconf as fallback

netdiscovery/netinventory:
* Enhanced Aruba IAP models support
Expand Down
50 changes: 34 additions & 16 deletions lib/GLPI/Agent/Task/Inventory/AIX/Bios.pm
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,20 @@ sub doInventory {
my $inventory = $params{inventory};
my $logger = $params{logger};

my ($ssn, $bios_version);
my $bios = _getInfos(logger => $logger);

my @infos = getLsvpdInfos(logger => $logger);
$inventory->setBios($bios);
}

sub _getInfos {
my (%params) = @_;

my @infos = getLsvpdInfos(%params);

my $bios ={
BMANUFACTURER => 'IBM',
SMANUFACTURER => 'IBM',
};

# Get the BIOS version from the System Microcode Image (MI) version, in
# 'System Firmware' section of VPD, containing three space separated values:
Expand All @@ -35,39 +46,46 @@ sub doInventory {
if ($system) {
# we only return the currently booted firmware
my @firmwares = split(' ', $system->{MI});
$bios_version = $firmwares[0];
$bios->{BVERSION} = $firmwares[0];
}

my $vpd = first { $_->{DS} eq 'System VPD' } @infos;
if ($vpd) {
$bios->{SSN} = $vpd->{SE} || "";
$bios->{SMODEL} = $vpd->{TM} || "";
}

# Use lsconf if lsvpd is not usable
unless ($bios->{SSN} && $bios->{SMODEL} && $bios->{BVERSION}) {
my $lsconf = getLsconfInfos(%params);
if ($lsconf) {
$bios->{SSN} = $lsconf->{"Machine Serial Number"} || "";
$bios->{BVERSION} = $lsconf->{"Platform Firmware level"} || "";
($bios->{SMANUFACTURER}, $bios->{SMODEL}) = split(",", $lsconf->{"System Model"} || "");
}
}

my $unameL = Uname("-L");
# LPAR partition can access the serial number of the host computer
$ssn = $vpd->{SE};
if ($unameL && $unameL =~ /^(\d+)\s+\S+/) {
if ($bios->{SSN} && $unameL && $unameL =~ /^(\d+)\s+\S+/) {
my $name = $1;
my $lparname = getFirstMatch(
logger => $logger,
logger => $params{logger},
command => "lparstat -i",
pattern => qr/Partition Name.*:\s+(.*)$/
pattern => qr/Partition\s+Name.*:\s+(.*)$/
);
# But an lpar can be migrated between hosts then we don't use to not have
# a SSN change during such migration. Anyway there's still a risk a given
# lparname is also used on another AIX system, administrators should avoid
# such usage as they won't be able to migrate the 2 LPARs on the same server
if ($lparname) {
$ssn = "aixlpar-$vpd->{SE}-$lparname";
$bios->{SSN} = "aixlpar-$bios->{SSN}-$lparname";
} else {
$ssn = "aixlpar-$vpd->{SE}-$name";
$bios->{SSN} = "aixlpar-$bios->{SSN}-$name";
}
}

$inventory->setBios({
BMANUFACTURER => 'IBM',
SMANUFACTURER => 'IBM',
SMODEL => $vpd->{TM},
SSN => $ssn,
BVERSION => $bios_version,
});
return $bios;
}

1;
28 changes: 28 additions & 0 deletions lib/GLPI/Agent/Tools/AIX.pm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use GLPI::Agent::Tools;

our @EXPORT = qw(
getLsvpdInfos
getLsconfInfos
getAdaptersFromLsdev
);

Expand Down Expand Up @@ -50,6 +51,33 @@ sub getLsvpdInfos {
return @devices;
}

sub getLsconfInfos {
my (%params) = (
command => 'lsconf',
@_
);

my @lines = getAllLines(%params)
or return;

my ($key, $infos);

foreach my $line (@lines) {
$line =~ s/\r$//;
if ($line =~ /^(\S[^:]+) : \s+ (.+) \s*$/x) {
$infos->{$1} = $2;
} elsif ($line =~ /^\s*$/) {
undef $key;
} elsif ($key && $line =~ /^\s+ (\S[^:]+) : \s+ (.+) \s*$/x) {
$infos->{$key}->{$1} = $2;
} elsif (!$key && $line =~ /^\S/) {
$key = $line;
}
}

return $infos;
}

sub getAdaptersFromLsdev {
my (%params) = (
command => 'lsdev -Cc adapter -F "name:type:description"',
Expand Down
72 changes: 72 additions & 0 deletions t/agent/tools/aix.t
Original file line number Diff line number Diff line change
Expand Up @@ -1934,6 +1934,71 @@ my %lsvpd_tests = (
],
);

my %lsconf_tests = (
'ibm-7040-681' => {
'Platform Firmware level' => '3H041021',
'Full Core' => 'true',
'Network Information' => {
'Sub Netmask' => '255.255.255.128',
'Name Server' => '9.20.136.11',
'Gateway' => '9.20.136.1',
'Host Name' => 'bb1p5-1.hursley.ibm.com',
'IP Address' => '9.20.136.92',
'Domain Name' => 'hursley.ibm.com'
},
'Processor Type' => 'PowerPC_POWER4',
'Good Memory Size' => '10240 MB',
'Firmware Version' => 'IBM,RG041021_d78e05_s',
'Paging Space Information' => {
'Total Paging Space' => '512MB',
'Percent Used' => '21%'
},
'Kernel Type' => '64-bit',
'Processor Clock Speed' => '1100 MHz',
'Number Of Processors' => '8',
'Console Login' => 'enable',
'LPAR Info' => '5 JAVADEV1 - kukicha',
'Memory Size' => '10240 MB',
'CPU Type' => '64-bit',
'System Model' => 'IBM,7040-681',
'Auto Restart' => 'true',
'Machine Serial Number' => '835A7AA'
},
'ibm-9080-m9s' => {
'Auto Restart' => 'true',
'LPAR Info' => '7 aix45',
'Console Login' => 'enable',
'Full Core' => 'false',
'Memory Size' => '8192 MB',
'Processor Type' => 'PowerPC_POWER9',
'Good Memory Size' => '8192 MB',
'Network Information' => {
'Gateway' => '192.168.1.1',
'Name Server' => '192.168.1.10',
'IP Address' => '192.168.1.45',
'Host Name' => 'aix45',
'Domain Name' => 'domain.org',
'Sub Netmask' => '255.255.255.0'
},
'Processor Clock Speed' => '3400 MHz',
'Paging Space Information' => {
'Percent Used' => '0%',
'Total Paging Space' => '20912MB'
},
'Number Of Processors' => '1',
'Kernel Type' => '64-bit',
'Processor Version' => 'PV_9_Compat',
'Firmware Version' => 'IBM,FW950.40 (VH950_099)',
'Processor Implementation Mode' => 'POWER 9',
'Machine Serial Number' => '45XY777',
'NX Crypto Acceleration' => 'Capable and Enabled',
'CPU Type' => '64-bit',
'In-Core Crypto Acceleration' => 'Capable, but not Enabled',
'Platform Firmware level' => 'VH950_099',
'System Model' => 'IBM,9080-M9S'
},
);

my %lsdev_tests = (
'aix-5.3a' => [
{
Expand Down Expand Up @@ -2214,6 +2279,7 @@ my %lsdev_tests = (

plan tests =>
(scalar keys %lsvpd_tests) +
(scalar keys %lsconf_tests) +
(scalar keys %lsdev_tests);

foreach my $test (keys %lsvpd_tests) {
Expand All @@ -2222,6 +2288,12 @@ foreach my $test (keys %lsvpd_tests) {
cmp_deeply(\@infos, $lsvpd_tests{$test}, "$test lsvpd parsing");
}

foreach my $test (keys %lsconf_tests) {
my $file = "resources/aix/lsconf/$test";
my $infos = getLsconfInfos(file => $file);
cmp_deeply($infos, $lsconf_tests{$test}, "$test lsconf parsing");
}

foreach my $test (keys %lsdev_tests) {
my $file = "resources/aix/lsdev/$test-adapter";
my @adapters = getAdaptersFromLsdev(file => $file);
Expand Down
152 changes: 152 additions & 0 deletions t/tasks/inventory/aix/bios.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#!/usr/bin/perl

use strict;
use warnings;
use lib 't/lib';

use Test::Deep;
use Test::Exception;
use Test::More;
use Test::NoWarnings;
use Test::MockModule;

use GLPI::Test::Inventory;
use GLPI::Agent::Task::Inventory::AIX::Bios;

my %tests = (
'aix-5.3a' => {
UnameL => "",
infos => {
BMANUFACTURER => 'IBM',
SMANUFACTURER => 'IBM',
BVERSION => 'SF240_202',
SSN => '65DEDAB',
SMODEL => '9111-520',
}
},
'aix-5.3b' => {
UnameL => "",
infos => {
BMANUFACTURER => 'IBM',
SMANUFACTURER => 'IBM',
BVERSION => 'MB245_300_008',
SSN => '99DXY4Y',
SMODEL => '8844-31X',
}
},
'aix-5.3c' => {
UnameL => "",
infos => {
BMANUFACTURER => 'IBM',
SMANUFACTURER => 'IBM',
BVERSION => 'EA350_074',
SSN => '106BDCA',
SMODEL => '7778-23X',
}
},
'aix-6.1a' => {
UnameL => "",
infos => {
BMANUFACTURER => 'IBM',
SMANUFACTURER => 'IBM',
BVERSION => 'AL710_099',
SSN => '10086CP',
SMODEL => '8233-E8B',
}
},
'aix-6.1b' => {
UnameL => "",
infos => {
BMANUFACTURER => 'IBM',
SMANUFACTURER => 'IBM',
BVERSION => 'EA350_038',
SSN => '066B96A',
SMODEL => '7998-60X',
}
},
'aix-6.1b sample1' => {
UnameL => "1234 sample1",
infos => {
BMANUFACTURER => 'IBM',
SMANUFACTURER => 'IBM',
BVERSION => 'EA350_038',
SSN => 'aixlpar-066B96A-sample1',
SMODEL => '7998-60X',
}
},
'aix-6.1b no-lparstat' => {
UnameL => "1234 no-lparstat",
infos => {
BMANUFACTURER => 'IBM',
SMANUFACTURER => 'IBM',
BVERSION => 'EA350_038',
SSN => 'aixlpar-066B96A-1234',
SMODEL => '7998-60X',
}
},
'ibm-7040-681' => {
UnameL => "",
infos => {
BMANUFACTURER => 'IBM',
SMANUFACTURER => 'IBM',
BVERSION => '3H041021',
SSN => '835A7AA',
SMODEL => '7040-681',
}
},
'ibm-9080-m9s' => {
UnameL => "",
infos => {
BMANUFACTURER => 'IBM',
SMANUFACTURER => 'IBM',
BVERSION => 'VH950_099',
SSN => '45XY777',
SMODEL => '9080-M9S',
}
},
);

plan tests => (2 * scalar keys %tests) + 1;

my $module = Test::MockModule->new(
'GLPI::Agent::Task::Inventory::AIX::Bios'
);

my $inventory = GLPI::Test::Inventory->new();

foreach my $test (keys %tests) {
my ($file) = $test =~ /^(\S+)/;
my $lsvpd_file = "resources/aix/lsvpd/$file";
my $lsconf_file = "resources/aix/lsconf/$file";
my $UnameL = $tests{$test}->{UnameL} // "";
my $lparstat_file = $UnameL =~ /^\d+\s+(\S+)/ ? "resources/aix/lparstat/$1" : "";

# Fake Uname("-L") & getFirstMatch() calls
$module->mock(
'Uname',
sub {
return $UnameL;
}
);
$module->mock(
'getFirstMatch',
sub {
return $module->original('getFirstMatch')->(@_, file => $lparstat_file);
}
);

# We also have to force file loading while using lsconf
$module->mock(
'getLsconfInfos',
sub {
return $module->original('getLsconfInfos')->(@_, file => $lsconf_file);
}
);

my $infos = GLPI::Agent::Task::Inventory::AIX::Bios::_getInfos(file => $lsvpd_file);
cmp_deeply($infos, $tests{$test}->{infos}, "$test: parsing");

lives_ok {
$inventory->setBios($infos);
} "$test: registering";
}

0 comments on commit 6c81643

Please sign in to comment.