????
| Current Path : /lib/raider/Raider/Info/ |
| Current File : //lib/raider/Raider/Info/satascsiata.pm |
use strict;
use warnings;
package Raider::Info::satascsiata;
use base qw( Raider::Info );
use Raider::Notification::Email;
use Cwd ();
use JSON::Tiny qw(decode_json encode_json);
=head1 NAME
Raider::Info::satascsiata - satascsiata specific instructions for get-info
=head1 DESCRIPTION
satascsiata specific methods to gather information required for populating the .info
file.
=head1 USAGE
use Raider::Info::satascsiata;
my $noraidInfoObj = Raider::Info::satascsiata->new();
=head1 METHODS
=head2 get_info()
Initiates all needed steps to generate a finished satascsiata info file.
=head2 get_pci_id(\%args)
Returns the PCI ID of device.
=head2 get_disk_info(\%args)
Returns the info of a disk.
=head2 get_disks()
Return the disk devices we are working with.
=head2 get_satascsiata()
Return non raided disks.
=head2 is_hdd(\%args)
Returns 1 if device is a physical disk, 0 if not.
=head2 get_non_raid_devices()
Return non raided ID's.
=cut
sub get_info {
my $self = shift;
my $opts = shift;
my $found_numdrives_arr = $self->get_satascsiata();
my $found_numdrives = scalar(@{ $found_numdrives_arr });
my ($disks_struct,$unidentifiable_disks,$unidentifiable_disks_usb) = $self->get_disks();
my $d_struct_usb_storage = { };
# Onboard controller identification.
my $onboard_controller_id;
my $id_int_key;
my @onboard_controller_ids_raw = ();
for my $line ( split /^/, `lspci -n` ) {
# IDE/SATA AHCI
if ( $line =~ /^\S+\s+0101:\s+(\S+)/ || $line =~ /^\S+\s+Class\s+0101:\s+(\S+)/i ) {
$id_int_key = $1;
push(@onboard_controller_ids_raw, $id_int_key);
}
# SATA
elsif ( $line =~ /^\S+\s+0106:\s+(\S+)/ || $line =~ /^\S+\s+Class\s+0106:\s+(\S+)/i) {
$id_int_key = $1;
push(@onboard_controller_ids_raw, $id_int_key);
}
}
# Remove duplicates
my %seen = ();
my @onboard_controller_ids = grep { ! $seen{$_} ++ } @onboard_controller_ids_raw;
my $d_struct_controllers;
for my $onboard_cntrl_id ( @onboard_controller_ids ) {
$d_struct_controllers->{ $opts->{cntrl_cnt} } = {
identifier => "Onboard:::$onboard_cntrl_id",
logical_disks => {}
};
$onboard_controller_id = $opts->{cntrl_cnt};
$opts->{cntrl_cnt}++;
}
my $d_struct_disks = { };
my $storm_d_struct = { controllers => { }, };
$storm_d_struct->{'controllers'}->{ '0' } = { disks => { } };
$storm_d_struct->{'controllers'}->{'0'}->{'numarrays'} = '0';
$storm_d_struct->{'controllers'}->{'0'}->{'numdrives'} = $found_numdrives;
$storm_d_struct->{'controllers'}->{'0'}->{'make'} = 'N/A';
$storm_d_struct->{'controllers'}->{'0'}->{'model'} = 'N/A';
$storm_d_struct->{'controllers'}->{'0'}->{'firmware'} = 'N/A';
my @usb_disks = ();
my @onboard_controller_disks = ();
for my $disk ( @{ $disks_struct->{disk_cnt} } ) {
my $disk_id;
if ( defined("$disks_struct->{disk_info}->{ $disk }->{model}\:::$disks_struct->{disk_info}->{ $disk }->{serial}") ) {
$disk_id = "$disks_struct->{disk_info}->{ $disk }->{model}\:::$disks_struct->{disk_info}->{ $disk }->{serial}";
}
if ( $disks_struct->{disk_info}->{ $disk }->{udev_id_bus} =~ /usb/i ) {
push(@usb_disks, $disk_id);
}
else {
push(@onboard_controller_disks, $disk_id);
}
if ( defined($disk_id) ) {
$d_struct_disks->{ $opts->{disk_cnt} } = {
identifier => $disk_id,
size_mb => $disks_struct->{disk_info}->{ $disk }->{size_mb},
size_unparsed => $disks_struct->{disk_info}->{ $disk }->{size_unparsed},
serial => $disks_struct->{disk_info}->{ $disk }->{serial},
model => $disks_struct->{disk_info}->{ $disk }->{model},
type => $disks_struct->{disk_info}->{ $disk }->{disk_type},
firmware => $disks_struct->{disk_info}->{ $disk }->{firmware},
state => $disks_struct->{disk_info}->{ $disk }->{state},
block_device => $disks_struct->{disk_info}->{ $disk }->{block_device},
udev_id_bus => $disks_struct->{disk_info}->{ $disk }->{udev_id_bus}
};
if ( defined($disks_struct->{disk_info}->{ $disk }->{smart_attributes}) ) {
$d_struct_disks->{ $opts->{disk_cnt} }->{'smart_attributes'} = $disks_struct->{disk_info}->{ $disk }->{smart_attributes};
}
$opts->{disk_cnt}++;
}
$storm_d_struct->{'controllers'}->{'0'}->{'disks'}->{ $disk }->{'type'} = $disks_struct->{disk_info}->{ $disk }->{disk_type};
};
if ( defined($onboard_controller_id) ) {
$d_struct_controllers->{ $onboard_controller_id }->{'unidentifiable_disks'} = $unidentifiable_disks;
my $each_onboard_cntrl_pd_count = 0;
for my $each_onboard_cntrl_pd ( @onboard_controller_disks ) {
my $accessor_key;
foreach my $key ( keys %{ $d_struct_disks } ) {
if ( $d_struct_disks->{$key}->{identifier} =~ /$each_onboard_cntrl_pd/ ) {
$accessor_key = $key;
}
}
$d_struct_controllers->{ $onboard_controller_id }->{'logical_disks'}->{ $each_onboard_cntrl_pd_count }->{'size_mb'} = $d_struct_disks->{ $accessor_key }->{'size_mb'};
$d_struct_controllers->{ $onboard_controller_id }->{'logical_disks'}->{ $each_onboard_cntrl_pd_count }->{'block_device'} = $d_struct_disks->{ $accessor_key }->{'block_device'};
$d_struct_controllers->{ $onboard_controller_id }->{'logical_disks'}->{ $each_onboard_cntrl_pd_count }->{'physical_disks'} = [ $each_onboard_cntrl_pd ];
$each_onboard_cntrl_pd_count++;
}
}
# Increment passed controller counter for onboard USB if needed.
if ( defined($d_struct_controllers->{ $opts->{cntrl_cnt} }->{'identifier'}) ) {
$opts->{cntrl_cnt}++;
}
$d_struct_usb_storage->{ $opts->{cntrl_cnt} }->{'identifier'} = 'Onboard:::usb_storage';
$d_struct_usb_storage->{ $opts->{cntrl_cnt} }->{'unidentifiable_disks'} = $unidentifiable_disks_usb;
my $each_onboard_usb_pd_count = 0;
for my $each_onboard_usb_pd ( @usb_disks ) {
my $accessor_key;
foreach my $key ( keys %{ $d_struct_disks } ) {
if ( $d_struct_disks->{$key}->{identifier} =~ /$each_onboard_usb_pd/ ) {
$accessor_key = $key;
}
}
$d_struct_usb_storage->{ $opts->{cntrl_cnt} }->{'logical_disks'}->{ $each_onboard_usb_pd_count }->{'size_mb'} = $d_struct_disks->{ $accessor_key }->{'size_mb'};
$d_struct_usb_storage->{ $opts->{cntrl_cnt} }->{'logical_disks'}->{ $each_onboard_usb_pd_count }->{'block_device'} = $d_struct_disks->{ $accessor_key }->{'block_device'};
$d_struct_usb_storage->{ $opts->{cntrl_cnt} }->{'logical_disks'}->{ $each_onboard_usb_pd_count }->{'physical_disks'} = [ $each_onboard_usb_pd ];
$each_onboard_usb_pd_count++;
}
$self->write_json({data => $storm_d_struct, device => 'satascsiata' });
return ($d_struct_usb_storage,$d_struct_controllers,$d_struct_disks,$opts->{cntrl_cnt},$opts->{disk_cnt});
}
sub get_pci_id {
my $self = shift;
my $opts = shift;
my $pci_id;
my $is_ide_short_circuit = 0;
my $all_bdev_ctrls = $self->get_nonraid_devs_to_path();
while ( my($device, $device_path) = each %{ $all_bdev_ctrls } ) {
if ( $device =~ /$opts->{device}/ ) {
if ( $device_path =~ /ide-/ ) {
$is_ide_short_circuit = 1;
}
else {
if ( $device_path =~ /\/sys\/devices\/[A-z]+\d+:\d+\/\d+:(\S+:\S+\.\d+)\// ) {
$pci_id = $self->get_device_id({ device_path => $device_path });
}
else {
$self->logger({ cat => 'c', msg => "Failed to extract pci_id from [$device_path]" });
}
}
}
};
return 'IDE' if ( $is_ide_short_circuit );
my $pci_id_desc;
for my $line ( split /^/, `lspci` ) {
if ( $pci_id && $line =~ /$pci_id/ ) {
$line =~ /$pci_id\s+(.*)/;
$pci_id_desc = $1;
}
}
return $pci_id_desc;
}
sub get_disk_info {
my $self = shift;
my $opts = shift;
my $device_name = substr $opts->{device}, 5, 3;
my ($contains,$pci_id);
my $size_mb = 0;
my $size_unparsed = 'unknown';
my $dtype = 'unknown';
my $model = 'unknown';
my $firmware = 'unknown';
my $serial = 'unknown';
my $state = 'unsupported';
#
# disk type
###############################################################################################
##
## SSD
##
if ( -e "/sys/block/$device_name/device/vendor" ) {
open FILE, "</sys/block/$device_name/device/vendor";
$contains = do { local $/; <FILE> };
close(FILE);
if ( $contains =~ /SSD|KINGSTON|INTEL|CRUCIAL/i ) {
$dtype = 'SSD';
}
}
for my $line ( split /^/, `sginfo -z /dev/$device_name` ) {
if ( $line =~ /Product:/i ) {
if ( $line =~ /^M4-CT|SSD|^CT|^SKC|kingston|^C300-|crucial|intel/i ) {
$dtype = 'SSD';
}
}
}
##
## ZDRIVE
##
if ( -e "/sys/block/$device_name/device/vendor" ) {
$contains = `grep -q "OCZ" /sys/block/$device_name/device/vendor`;
if ( $? == 0 ) {
$dtype = 'ZDRIVE';
}
}
$pci_id = $self->get_pci_id({ device => "$opts->{device}" });
if ( $pci_id =~ /SATA/i ) {
$dtype = 'SATA';
}
elsif ( $pci_id =~ /SCSI/i ) {
$dtype = 'SCSI';
}
elsif ( $pci_id =~ /IDE/i ) {
$dtype = 'PATA';
}
elsif ( $pci_id =~ /SAS/i ) {
$dtype = 'SAS';
}
my $hdparm_info;
if ( $dtype eq 'PATA' ) {
$hdparm_info = `hdparm -i $opts->{device}`;
}
else {
$hdparm_info = `hdparm -I $opts->{device}`;
}
my $smartctl_info = `smartctl -i $opts->{device} -T permissive`;
if ( $hdparm_info =~ /Nominal\s+Media\s+Rotation\s+Rate:\s+Solid\s+State\s+Device/i ) {
$dtype = 'SSD';
}
#
# disk size
###############################################################################################
my $sectors = 0;
my $hdparm_output_geo = `hdparm -g $opts->{device}`;
if ( $hdparm_output_geo =~ /geometry\s+=\s+\S+\s+sectors\s+=\s+(\d+)/i ) {
$sectors = $1;
}
if ( $hdparm_output_geo =~ /(geometry\s+=\s+\S+\s+sectors\s+=.+)/i ) {
$size_unparsed = $1;
}
# 512 bytes per sector..
my $in_bytes = $sectors * 512;
my $in_kb = $in_bytes / 1024;
$size_mb = $in_kb / 1024;
#
# disk model
###############################################################################################
if ( $hdparm_info =~ /Model\s+Number(\s+)?:(.+)/i ) {
$model = $2;
$model =~ tr/ //ds;
}
elsif ( $smartctl_info =~ /Device\sModel(\s+)?:(.+)/i ) {
$model = $2;
$model =~ tr/ //ds;
}
elsif ( $smartctl_info =~ /Device(\s+)?:(.+)/i ) {
$model = $2;
$model =~ tr/ //ds;
}
#
# disk firmware
###############################################################################################
if ( $hdparm_info =~ /Firmware\s+Revision(\s+)?:(.+)/i ) {
$firmware = $2;
$firmware =~ tr/ //ds;
}
elsif ( $smartctl_info =~ /Firmware\s+Version(\s+)?:(.+)/i ) {
$firmware = $2;
$firmware =~ tr/ //ds;
}
#
# disk serial
###############################################################################################
if ( $hdparm_info =~ /Serial\s+Number(\s+)?:(.+)/i ) {
$serial = $2;
$serial =~ tr/ //ds;
}
elsif ( $smartctl_info =~ /Serial\s+Number(\s+)?:(.+)/i ) {
$serial = $2;
$serial =~ tr/ //ds;
}
#
# UDEV
###############################################################################################
# Directly querying the disk for model/serial works well when the disk responds. However, since we ideally want to be able to uniquely
# identify a disk, and our current identification system used by Sonar relies on $model-$serial identification, query udev db for
# model/serial as well. This covers the scenario where a disk may be failed and not responding to requests, but the serial/model still
# lives in the udev db. Obviously this isn't perfect , but covers the scenario where a disk fails after the udev db was generated, so that
# we can still get the failed disks model/serial.
#
# -- ssullivan May 15, 2013
my $udev_info;
if ( $serial eq 'unknown' || $model eq 'unknown' ) {
$udev_info = $self->get_udev_block_device_info({ block_device_name => $device_name });
# When querying disk directly for model-serial; use the udev info only on failure.
if ( ref($udev_info) eq 'HASH' && defined($udev_info->{model}) && defined($udev_info->{id_serial}) ) {
$model = $udev_info->{model};
$serial = $udev_info->{id_serial};
}
}
else {
$udev_info = $self->get_udev_block_device_info({ block_device_name => $device_name });
}
# SMART health status doesn't seem to work with flash drives, so fudge it.
if ( $model =~ /Flash_Disk/i ) {
$dtype = 'Flash_Disk';
$state = 'Present';
}
elsif ( ref($udev_info) eq 'HASH' && $udev_info->{disk_bus} =~ /usb/i ) {
$dtype = 'USB_ATA';
}
# We don't want the block device of a RAID LD to show up.
elsif ( ref($udev_info) eq 'HASH' && $udev_info->{id_vendor} =~ /^lsi|^adaptec|^3ware/i ) {
return 'skip';
}
#
# disk state & SMART attributes
###############################################################################################
my $smart_attribs = 'unsupported';
if ( `smartctl -H $opts->{device} -T permissive -s on` =~ /SMART\s+overall-health\s+self-assessment\s+test\s+result(\s+)?:\s+(.+)/i ) {
$state = $2;
}
# SMART attributes
if ( ref($udev_info) eq 'HASH' && $udev_info->{disk_bus} =~ /usb/i ) {
$smart_attribs = $self->get_smart_attribs({ device => $opts->{device}, bus => 'usb' });
}
else {
$smart_attribs = $self->get_smart_attribs({ device => $opts->{device} });
}
$smart_attribs = 'unsupported' if ( defined($smart_attribs->{error}) );
if ( ref($udev_info) eq 'HASH' ) {
return ($dtype,$size_mb,$model,$firmware,$serial,$state,$smart_attribs,$size_unparsed,$udev_info->{disk_bus});
}
else {
return ($dtype,$size_mb,$model,$firmware,$serial,$state,$smart_attribs,$size_unparsed,'unknown');
}
}
sub get_disks {
my $self = shift;
my $found_numdrives_arr = $self->get_satascsiata();
my $dnum = 0;
my $struct = {
disk_cnt => [],
disk_info => {}
};
my $unidentifiable_disks = 0;
my $unidentifiable_disks_usb = 0;
if ( @{ $found_numdrives_arr } ) {
for my $each_disk ( @{ $found_numdrives_arr } ) {
my ($disk_type,$size_mb,$model,$firmware,$serial,$state,$smart_attribs,$size_unparsed,$udev_id_bus) = $self->get_disk_info({ device => $each_disk });
next if ( $disk_type eq 'skip' );
if ( $model eq 'unknown' || $serial eq 'unknown' ) {
if ( $udev_id_bus =~ /usb/i ) {
$unidentifiable_disks_usb++;
}
else {
$unidentifiable_disks++;
}
next;
}
push(@{ $struct->{disk_cnt} }, $dnum);
$struct->{disk_info}->{ $dnum } = {
disk_type => $disk_type,
size_mb => $size_mb,
size_unparsed => $size_unparsed,
model => $model,
firmware => $firmware,
serial => $serial,
state => $state,
block_device => $each_disk,
udev_id_bus => $udev_id_bus
};
if ( $smart_attribs ne 'unsupported' ) {
$struct->{disk_info}->{ $dnum }->{'smart_attributes'} = $smart_attribs;
}
$dnum++;
}
}
return ($struct,$unidentifiable_disks,$unidentifiable_disks_usb);
}
sub get_nonraid_devs_to_path {
my $self = shift;
my $opts = shift;
my $data;
my $lspci_output = `lspci`;
for our $device ( @{ $self->get_non_raid_devices() } ) {
# Filter out FusionMPTSAS2 devices from this. We want them to show up as
# attached to their specific controller, not as directly connected through
# the motherboard.
if ( $lspci_output =~ /$device\s+.+Fusion-MPT\s+SAS-2/i ) {
$self->logger({ cat => 'i', msg => "Filtering out [$device] from Info/satascsiata as it's a FusionMPTSAS2 controller" });
next;
}
my $all_bdev_ctrls = $self->get_sys_ctrls_with_bdevs();
for my $device_path ( keys %{ $all_bdev_ctrls } ) {
# If this block device does not belong to our current controller, go to
# next loop pass.
next unless ( $device_path =~ /$device/ );
$data->{ "/dev/$all_bdev_ctrls->{ $device_path }" } = $device_path;
}
}
return $data;
}
sub get_satascsiata {
my $self = shift;
my $opts = shift;
my @found_numdrives_arr;
my $d_struct = $self->get_nonraid_devs_to_path();
while ( my($device, $device_path) = each %{ $d_struct } ) {
if ( $self->is_hdd({ device => $device }) ) {
push(@found_numdrives_arr, $device);
}
}
return \@found_numdrives_arr;
}
sub is_hdd {
my $self = shift;
my $opts = shift;
# Returns:
# 0 -- if device is not a physical disk
# 1 -- if device is a physical disk
my $device_short;
if ( $opts->{device} =~ /\/dev\/(\S+)/ ) {
$device_short = $1;
}
else {
$self->logger({ cat => 'c', msg => "is_hdd() [$opts->{device}] is of invalid type!" });
}
# Filter out CDROM device
# Some old hosts, like Cent5s, will sometimes show the CDROM as hda.
# Account for this situation.
if ( -e '/proc/sys/dev/cdrom/info' ) {
open(my $fh, '/proc/sys/dev/cdrom/info' )
or $self->logger({
cat => 'c',
msg => "Unable to open [/proc/sys/dev/cdrom/info]: $!"
});
while (my $line = <$fh>) {
if ( $line =~ /^drive\s+name:\s+(\S+)/ ) {
if ( $1 eq $device_short ) {
return 0;
}
}
}
}
return 0 if ( $device_short =~ /^sr[0-9]+/ );
# If the device name is of format fd[0-9]+ throw it out, as assume its a
# floppy device.
return 0 if ( $device_short =~ /^fd[0-9]+/ );
# No entry in /sys/block ? Reject.
return 0 unless ( -d "/sys/block/$device_short" );
# Somehow doesn't exist? Reject.
return 0 unless ( -e $opts->{device} );
# If the size of the device is reported as 0, reject.
if ( -e "/sys/block/$device_short/size" ) {
my $device_size;
open(my $fh, "/sys/block/$device_short/size")
or $self->logger({
cat => 'c',
msg => "Unable to open [/sys/block/$device_short/size]: $!"
});
while (my $line = <$fh>) {
chomp $line;
$device_size = $line;
}
# 0 size, assume not a block device. Among likely other things, this gets
# rid of loop devices from detecting as a physical disk.
if ( $device_size == 0 ) {
return 0;
}
}
else {
# No size? reject.
return 0;
}
# With 2.6.32 (Cent6) and newer, there is a /sys/devices/virtual/block/
# directory. Virtual devices like loop, dm, and md, devices show up in here
# (which also show up in /sys/block). If /sys/devices/virtual/block/ exists,
# filter out (reject) devices that show up here.
if ( -d '/sys/devices/virtual/block' ) {
return 0 if ( -e "/sys/devices/virtual/block/$device_short" );
}
else {
return 0 if ( $device_short =~ /^loop[0-9]+/ );
return 0 if ( $device_short =~ /^md[0-9]+/ );
return 0 if ( $device_short =~ /^dm-[0-9]+/ );
return 0 if ( $device_short =~ /^ram[0-9]+/ );
}
# Filter out things we gleam from basic SMART info that give this away as
# not a physical disk.
for my $line ( split /^/, `smartctl -i $opts->{device}` ) {
# Filter out Adaptec RAID LDs
if ( $line =~ /(Device|Vendor)\s*:\s+(Adaptec|ASR\S+)/i ) {
return 0;
}
# Filter out LSI RAID LDs
elsif ( $line =~ /(Device|Vendor)\s*:\s+LSI|megaraid/i ) {
return 0;
}
# Filter out 3ware RAID LDs
elsif ( $line =~ /(Device|Vendor)\s*:\s+3ware/i ) {
return 0;
}
# iSCSI disk
elsif ( $line =~ /(Device|Vendor)\s*:\s+IET/i ) {
return 0;
}
# iSCSI disk
elsif ( $line =~ /(Product)\s*:\s+VIRTUAL-DISK/i ) {
return 0;
}
}
# If we made it this far, assume its a physical disk.
return 1;
}
sub get_non_raid_devices {
my $self = shift;
my $all_bdev_ctrls = $self->get_sys_ctrls_with_bdevs();
my @nonraid_bdev_ctrls = ();
my $lspci_output = `lspci`;
# in this path:
# /sys/devices/pci0000:00/0000:00:01.1/0000:02:00.0/host0/target0:2:0/0:2:0:0/block
# 00:01.1 is the address of the PCI slot:
# 00:01.1 PCI bridge: Intel Corporation Xeon E3-1200 v3/4th Gen Core Processor PCI Express x8 Controller (rev 06)
# 02:00.0 is the address of the raid controller:
# 02:00.0 RAID bus controller: Broadcom / LSI MegaRAID Tri-Mode SAS3516 (rev 01)
# thus in these scenarios, we would need to look and see if this block device maps to 02:00.0
# in this path:
# /sys/devices/pci0000:00/0000:00:1f.2/ata1/host1/target1:0:0/1:0:0:0/block
# 00:1f.2 is the address of a SATA port on the motherboard:
# 00:1f.2 SATA controller: Intel Corporation 8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] (rev 05)
# Since its directly attached, there is no address after that. Thus in these scenarios, we need to look
# and see if this block device maps to 00:1f.2
for my $bdev_ctrl_path ( keys %{ $all_bdev_ctrls } ) {
# given this path /sys/devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block
# would try to match on 00:1f.2
my $ctrl_id;
if ( $bdev_ctrl_path =~ /\/sys\/devices\/\S+\d+:\d+\/\d+:(\d+:\S+\.\d+)/ ) {
# if theres a controller connected to the base address, $1 will look like this:
# 00:01.1/0000:02:00.0
# So we check for the presence of /, and treat it as true/false
my ($has_ctrl) = $1 =~ /\// ? 1 : 0;
unless ($has_ctrl) {
$ctrl_id = $self->get_device_id({ device_path => $bdev_ctrl_path });;
}
}
if ($ctrl_id) {
for my $line ( split /^/, $lspci_output ) {
# If our block device is _not_ raid..
if ( $line =~ /^$ctrl_id/i && $line !~ /RAID/i ) {
# Perl 5.8.8 doesn't support the below commented code..
#if ( $ctrl_id ~~ @nonraid_bdev_ctrls ) {
my %nonraid_bdev_ctrls_bash = map { $_ => 1 } @nonraid_bdev_ctrls;
if ( exists($nonraid_bdev_ctrls_bash{$ctrl_id}) ) {
# Dont duplicate it.
next;
}
else {
push(@nonraid_bdev_ctrls, $ctrl_id);
}
}
}
}
else {
$self->logger({ cat => 'w', msg => "get_non_raid_devices() Skipping device [$bdev_ctrl_path]" });
}
}
return \@nonraid_bdev_ctrls;
}
1;