# # Copyright (c) 2001, 2009, Oracle and/or its affiliates.All rights reserved. # # $Id: sRawmetrics.pm /stpl_db_11.2_aix.ppc64/1 2009/02/25 23:08:53 rajverma Exp $ # # # NAME # sRawmetrics.pm # # DESC # AIX storage info # # # FUNCTIONS # # # NOTES # # # MODIFIED (MM/DD/YY) # rajverma 02/23/09 - Add config file changes. # sejain 10/03/07 - bug-6398412 : changing call to /usr/sysv/bin/df via nmhs # svrrao 09/13/07 - Porting merge for bug fix 6002107, hang with df -P # sejain 06/13/07 - bug-6111302 : lsattr getting picked from the wrong path # sejain 02/01/07 - bug:5738360 - fixing hard coded path for lsdev & lsvg # nsharma 04/07/06 - Ignore offline volume groups # ssreenat 05/10/05 - Disk Metrics implementation # ssreenat 08/08/05 - Added filesystems,lvm metrics # ssreenat 11/08/05 - Created # # # # Initialize the environment variables at compile time BEGIN { $ENV{PATH} = "$ENV{ORACLE_HOME}/bin:$ENV{ORACLE_HOME}/emagent/bin:/etc:/usr/sbin:/usr/bin" } package storage::sRawmetrics; require v5.6.1; use strict; use warnings; use locale; use File::Basename; use File::Spec::Functions; use File::Path; use Cwd; use URI::file; use storage::sUtilities; use constant NIL => ''; #------------------------------------------------ # Global package variable to hold sub name our $AUTOLOAD; #------------------------------------------------ # subs declared #----------------------------------------------- sub get_disk_metrics; sub get_filesystem_metrics ( ); sub get_virtualization_layer_metrics(); sub lvmMetrics(); sub runShowmount ( $ ); #------------------------------------------------- # Variables in package scope #------------------------------------------------ # Variable for logical to physical map for all disk slices #------------------------------------------------------------------------------------ # Static Configuration #------------------------------------------------------------------------------------ #-------------------------------------------------------- # Filesystem metric specific configuration #-------------------------------------------------------- $storage::Register::config{key}{default}= "serial_no fc_id"; # df shows swap filesystems only as "swap". `swapinfo` shows a list of # filesystems that are used for swap space. $storage::Register::config{filesystem}{command}{swap} = "lsps -a"; # NFS equivalent filetypes $storage::Register::config{filesystem}{nfsfstypes} = "nfs3"; # Filesystems to skip, need not instrument metrics for these filesystems $storage::Register::config{filesystem}{skipfilesystems} = "mvfs|procfs|fd|mntfs|tmpfs|cachefs|shm|cdfs|hsfs|lofs|afs"; #----------------------------------------------------------------------------------------- # FUNCTION : get_disk_metrics # # DESC # return a pointer to a array of references to hashes for all volume manager metrics # # ARGUMENTS # #----------------------------------------------------------------------------------------- sub get_disk_metrics { my @diskdevices; my %disklist; # Hash of disks and partitions my %disks; # Hash of disks my $major; my $minor; my $name; my $vendor; my $product; my $size; my $sizeb; my $rev; my $state; my $serial_no; my $bus; my $block_name; my $char_name; my $driver; my $desc; my $pdevname; my %empartition ; # Hash for the empartitions. my @em_rows; my @partitions = storage::Utilities::getConfig("Disks"); my @cnt = storage::Utilities::getConfig("Collection Size"); # Retrieve the maximum number of disks to be monitorerd from the config file my $temp; my $cnt_obj; my $dsk_cnt = 100; for my $res (@cnt) { ($temp , $cnt_obj) = split(/=/,$res) ; if ($temp =~ /Disk/i) { $dsk_cnt=$cnt_obj; last; } } foreach my $ptn (@partitions) { chomp $ptn; # Skip Blank Lines next unless $ptn; $ptn =~ s/^\s+|\s+$//g; $empartition{$ptn} = $ptn; } my @disk_rows = run_system_command("/etc/lsdev -Cc disk -F'name;status;description'"); # If the number of disks being monitored is greated than Disk count then # display warning message and request the user to edit the file. if (( $#disk_rows >= $dsk_cnt) && !(keys(%empartition) )) { storage::Utilities::setConfig("Disks","0"); storage::Register::log_error_message("The number of Disks to be monitored is larger than $dsk_cnt. Please add the disks to be monitored in the config file emagent_storage.config"); } else { storage::Utilities::setConfig("Disks","1"); } # AIX doesnt have physical partitions on disk. They use LVM to partition.So we are not instrumenting physical partition info # Get the lists of disks with status and description for my $disk_row (@disk_rows) { last if (@diskdevices == $dsk_cnt); chomp $disk_row; next unless $disk_row; $disk_row =~ s/^\s+|\s+$//g; $major = NIL; $serial_no = NIL; $name = NIL; $minor = NIL; $vendor = NIL; $product = NIL; $size = NIL; $sizeb = NIL; $rev = NIL; $bus = NIL; $block_name = NIL; $char_name = NIL; $driver = NIL; $desc = NIL; $pdevname = NIL; my $char_prefix = "/dev/r"; my %devinfo; my @col=split /;/,$disk_row; $name = $col[0]; $state = $col[1]; $desc = $col[2]; $block_name = "/dev/$name"; $char_name="$char_prefix$name"; next if( (keys( %empartition ) > 0) && ($empartition{$name} ne $name) ); # Instrument only if the disk is available if ($state ne "Available") { next; } # Get the major and minor number of the disk for my $istat_row (run_system_command("istat $block_name")) { chomp $istat_row; next unless $istat_row; $istat_row =~ s/^\s+|\s+$//g; if ($istat_row =~ /Major/i) { my @col = split /\s+/, $istat_row; $major = $col[2]; $minor = $col[5]; last; } } # Instrument the bus type/driver info if ($disk_row =~ /SCSI/) { $bus = "SCSI"; $driver = "scdisk"; } if ($disk_row =~ /SSA/) { my $connwhere_shad_value; my $conn_flag=0; $bus = "SSA"; $driver = "ssadisk"; $connwhere_shad_value = NIL; $pdevname = NIL; for my $ssa_row (run_system_command("odmget -qname=$name CuAt")) { if ($ssa_row =~ /connwhere_shad/) { $conn_flag = 1; next; } if ($conn_flag eq 1) { $conn_flag = 0; if ($ssa_row =~ /value/) { my $ignore; ($ignore, $connwhere_shad_value) = split("=", $ssa_row); $connwhere_shad_value =~ s/"//g; $connwhere_shad_value = trim($connwhere_shad_value); last; } } $conn_flag = 0; } if ($connwhere_shad_value ne NIL) { for my $ssa_row (run_system_command("odmget -qvalue=$connwhere_shad_value CuAt")) { if ($ssa_row =~ /pdisk/) { my $ignore; ($ignore, $pdevname) = split("=",$ssa_row); $pdevname =~ s/"//g; $pdevname = trim($pdevname); last; } } } } # This corresponds to fibre Channel Disk Array device if ($disk_row =~ /Disk Array Device/) { my $dac; $bus = "FAStT"; $driver = "fcd"; my $model = $desc; $model =~ s/ .*//; $pdevname = run_system_command("lsdev -C | grep $model| grep dac | tail -1"); $pdevname =~ s/ .*//; for ($dac = run_system_command("lsdev -C | grep $model| grep dac")) { my @col=split /\s+/,$dac; if ($col[1] =~ /Available/) { $pdevname = $col[0]; last; } } } if ($driver) { $devinfo{driver} = $driver; } $devinfo{name} = $block_name; $devinfo{major} = $major; $devinfo{minor} = $minor; $devinfo{nameinstance} = $name; $devinfo{type} = 'DISK'; $devinfo{partition} = 0; $devinfo{filetype} = get_file_type($devinfo{name}); $devinfo{char_name} = $char_name; # Vendor Information retrieval my $cmd; if (($bus eq "SSA" || $bus eq "FAStT") && $pdevname ne '') { $cmd = "lscfg -vpl $pdevname"; } else { $cmd = "lscfg -vpl $name"; } # Use the lscfg command to get the device specific info , vendor, product, ROS level and Serial Number (vendor specific) # The serial number is the only unique tag for each disk for my $diskinfo (run_system_command("$cmd")) { chomp($diskinfo); next unless $diskinfo; $diskinfo =~ s/^\s+|\s+$//g; if ($diskinfo =~ /Manufacturer/) { $diskinfo =~ s/.*\.//g; $vendor = $diskinfo; next; } if ($diskinfo =~ /Machine Type and Model/) { $diskinfo =~ s/.*\.//g; $product = $diskinfo; next; } if ($diskinfo =~ /ROS Level and ID/) { $diskinfo =~ s/.*\.//g; $rev = $diskinfo; next; } if ($diskinfo =~ /Serial Number/) { $diskinfo =~ s/.*\.//g; $serial_no = $diskinfo; next; } } if ($vendor ne '') { $devinfo{vendor} = $vendor; } if ($product ne '') { $devinfo{product} = $product; } if ($rev ne '') { $devinfo{rev_level} = $rev; } if ($serial_no ne '') { $devinfo{serial_no} = $serial_no; } else { # For FAStT type, we dont have the serial number instead the scsi id and LUN type if ($bus eq "FAStT") { my $lun_id= NIL; my $scsi_id= NIL; for my $lsattr_row (run_system_command("lsattr -El $name")) { chomp($lsattr_row); next unless $lsattr_row; $lsattr_row =~ s/^\s+|\s+$//g; if ($lsattr_row =~ /lun_id/) { my @col = split /\s+/,$lsattr_row; $lun_id = $col[1]; next; } if ($lsattr_row =~ /scsi_id/) { my @col = split /\s+/,$lsattr_row; $scsi_id = $col[1]; next; } } $devinfo{fc_id} = "$lun_id-$scsi_id"; } } # Calculate Size of a disk. This returns in MB $size = run_system_command("nmhs get_disk_size $name"); if ($size =~ /error::/) { warn "DEBUG: Unable to get device specific info for $name\n"; $size = 0; } $sizeb = $size *1024 * 1024; $devinfo{sizeb} = $sizeb; $devinfo{usedb} = $sizeb; $devinfo{freeb} = 0; $disks{$devinfo{nameinstance}} = \%devinfo if $devinfo{type} eq 'DISK'; # Keep an list indexed on nameinstance and type push @{$disklist{$devinfo{type}}{$devinfo{nameinstance}}}, \%devinfo; push @diskdevices, \%devinfo; } generateKeys( \%disks ) or warn "Failed to generate uniquely identifying disk_keys\n" and return; #---------------------------------------------- # Create slice keys and validate null fields # for disk records #---------------------------------------------- for my $dref ( values %disks ) { # Generate a slicekey for the disk $dref->{slice_key} = "$dref->{disk_key}"; } for my $diskref ( values %disks ) { # This is an error that should be handled warn "No nameinstance for disk $diskref->{name}\n" and next unless $diskref->{nameinstance}; #---------------------------------------------------------------- # if there is more than one disk for the name instance copy the # common fields #---------------------------------------------------------------- for my $dref( @{$disklist{DISK}{$diskref->{nameinstance}}} ) { # skip if its the same record as in diskref next if $dref eq $diskref; # Copy the common fields between disk record and current record for ( @{$storage::Register::config{diskfields}{DISK}} ) { $dref->{$_} = $diskref->{$_} if $diskref->{$_}; } } } #---------------------------------------------- # Copy the required fields for all records #---------------------------------------------- for my $entity_ref ( @diskdevices ) { $entity_ref->{key_value} = $entity_ref->{slice_key}; $entity_ref->{storage_layer} = 'OS_DISK'; $entity_ref->{entity_type} = 'Disk Partition' if $entity_ref->{type} =~ /PARTITION/i; ; $entity_ref->{entity_type} = 'Disk' if $entity_ref->{type} =~ /^DISK$/i; $entity_ref->{os_identifier} = $entity_ref->{name}; $entity_ref->{global_unique_id} = $entity_ref->{disk_key} if $entity_ref->{type} =~ /^DISK$/i; } return \@diskdevices; } #----------------------------------------------------------------------------------------- # FUNCTION : get_virtualization_layer_metrics # # DESC # return a array of hashes for all storage virtualization layers deployed on the host # Logical volume manager, Veritas VM etc # # ARGUMENTS # #----------------------------------------------------------------------------------------- sub get_virtualization_layer_metrics ( ) { my @results; for my $function_pointer ( \&lvmMetrics, \&get_veritas_volume_metrics) { my $results_ref = $function_pointer->(); next unless $results_ref and @{$results_ref}; push @results,@{$results_ref}; } return [()] unless @results; return \@results; } #----------------------------------------------------------------------------------------- # FUNCTION : lvmMetrics # # DESC # Returns an array with Hash Tables of each LVM Volume Logical Volumes # # ARGUMENTS # none #----------------------------------------------------------------------------------------- sub lvmMetrics() { my @aixlvmarray; my %emvolumes ; # Hash for the volumes form emagent_storage.config. my @volumes ; @volumes = storage::Utilities::getConfig("Volumes"); my @cnt = storage::Utilities::getConfig("Collection Size"); #Retrieve the maximum number of volume groups to be monitored my $temp; my $cnt_obj; my $vol_cnt = 10; for my $res (@cnt) { ($temp , $cnt_obj) = split(/=/,$res) ; if ($temp =~ /Volume/i) { $vol_cnt=$cnt_obj; last; } } foreach my $vol (@volumes) { chomp $vol; # Skip Blank Lines next unless $vol; $vol =~ s/^\s+|\s+$//g; $emvolumes{$vol} = $vol; } my @volume_rows = run_system_command("lsvg -o"); # If the number of Volumes being monitored is greater than Volumes count then # display warning message and request the user to edit the file. if (( $#volume_rows >= $vol_cnt) && !(keys(%emvolumes) )) { storage::Utilities::setConfig("Volumes","0"); storage::Register::log_error_message("The number of Volume groups to be monitored is larger than $vol_cnt. Please add the Volume groups to be monitored in the config file emagent_storage.config"); } else { storage::Utilities::setConfig("Volumes","1"); } my $vg_proc=0; warn "DEBUG: Unable to find executable /usr/sbin/lsvg for AIX LVM \n" and return unless -e '/usr/sbin/lsvg'; for (@volume_rows) { last if ($vg_proc == $vol_cnt); chomp; s/^\s+|\s+$//g; next unless $_; my %volume_group; ( $volume_group{name} ) = /(\S+)$/g; # Process only the volumes in the config file. next if( (keys( %emvolumes ) > 0) && ($emvolumes{$volume_group{name}} ne $volume_group{name} ) ); $volume_group{vendor} = 'AIX'; $volume_group{product} = 'LVM'; $volume_group{storage_layer} = 'VOLUME_MANAGER'; $volume_group{entity_type} = 'Volume Group'; $volume_group{key_value} = "aix_lvm_vg_$volume_group{name}"; $volume_group{sizeb} = 0; # all entities belonging to the volume push @{$volume_group{child_entity_criteria}} , { volume_group => $volume_group{name}, product => $volume_group{product} }; push @aixlvmarray,\%volume_group; $vg_proc++; # Instrument Physical Volume for (run_system_command("lsvg -p $volume_group{name}")) { chomp; s/^\s+|\s+$//g; my % physical_volume; next if /^(PV_NAME|$volume_group{name})/i; my @columns = split; $physical_volume{name} = $columns[0]; $physical_volume{status} = $columns[1]; $physical_volume{status} = uc($physical_volume{status}); $physical_volume{petotal} = $columns[2]; $physical_volume{pefree} = $columns[3]; $physical_volume{peallocated} = $physical_volume{petotal} - $physical_volume{pefree}; $physical_volume{vendor} = 'AIX'; $physical_volume{product} = 'LVM'; $physical_volume{storage_layer} = 'VOLUME_MANAGER'; $physical_volume{entity_type} = 'Physical Volume'; $physical_volume{os_identifier} = "/dev/$physical_volume{name}"; $physical_volume{volume_group} = $volume_group{name}; $physical_volume{key_value} = "aix_lvm_pv_$volume_group{name}_$physical_volume{name}"; # physical entities on the physical volume push @{$physical_volume{parent_entity_criteria}}, { entity_type => 'Physical Entity', volume_group => $volume_group{name} , product => $volume_group{product}, disk_name => $physical_volume{name} }; for my $pvrecord (run_system_command("lspv $physical_volume{name}")) { chomp $pvrecord; $pvrecord =~ s/^\s+|\s+$//g; next unless $pvrecord; if ($pvrecord =~ /PP\sSIZE/i) { my @col=split /\s+/,$pvrecord; $physical_volume{ppsize} = $col[2]; if ($col[3] =~ /megabyte/i) { $physical_volume{ppsize} *= 1048576 ; } if ($col[3] =~ /kilobyte|kb/i) { $physical_volume{ppsize} *= 1024; } } } my $pe_count = 0; # Disk slice instrumentation # Physical Entity for my $dsrecord (run_system_command("lspv -l $physical_volume{name}")) { my %disk_slice; chomp $dsrecord; $dsrecord =~ s/^\s+|\s+$//g; next unless $dsrecord; next if $dsrecord =~ /^(LV\sNAME|$physical_volume{name})/i; my @col=split /\s+/,$dsrecord; $pe_count++; $disk_slice{sizeb} = 0; $disk_slice{start} = $pe_count; $disk_slice{volume_name} = "/dev/$col[0]"; $disk_slice{pe} = $col[2]; $disk_slice{le} = $col[1]; $disk_slice{sizeb} = $disk_slice{pe} * $physical_volume{ppsize}; $disk_slice{disk_name} = $physical_volume{name}; $disk_slice{vendor} = 'AIX'; $disk_slice{product} = 'LVM'; $disk_slice{storage_layer} = 'VOLUME_MANAGER'; $disk_slice{entity_type} = 'Physical Entity'; $disk_slice{status} = $physical_volume{status}; $disk_slice{key_value} = "aix_lvm_pe_$volume_group{name}_$physical_volume{name}_$disk_slice{start}"; $disk_slice{volume_group} = $volume_group{name}; $disk_slice{name} = "$volume_group{name}_$physical_volume{name}_$disk_slice{start}"; # Physical volumes used by the physical entity push @{$disk_slice{child_entity_criteria}}, { entity_type => 'Physical Volume', volume_group => $volume_group{name}, product => $volume_group{product}, name=> $disk_slice{disk_name} }; # Volumes using the physical entity push @{$disk_slice{parent_entity_criteria}}, { entity_type => 'Volume', volume_group => $volume_group{name}, product => $volume_group{product}, os_identifier => $disk_slice{volume_name} }; push @aixlvmarray,\%disk_slice; } $physical_volume{sizeb} = $physical_volume{petotal} * $physical_volume{ppsize}; push @aixlvmarray, \%physical_volume; # Update the size of the volume group as sum of all disks $volume_group{sizeb} += $physical_volume{sizeb} if $physical_volume{sizeb}; } # Instrument Logical volume belonging to the Volume group for (run_system_command("lsvg -l $volume_group{name}")) { chomp; s/^\s+|\s+$//g; my %logical_volume; next if /^(LV\sNAME|$volume_group{name})/i; my @columns = split; $logical_volume{vendor} = 'AIX'; $logical_volume{product} = 'LVM'; $logical_volume{storage_layer} = 'VOLUME_MANAGER'; $logical_volume{entity_type} = 'Logical Volume'; $logical_volume{name} = $columns[0]; $logical_volume{os_identifier} = "/dev/$logical_volume{name}"; $logical_volume{volume_group} = $volume_group{name}; $logical_volume{key_value} = "aix_lvm_v_$volume_group{name}_$logical_volume{name}"; $logical_volume{status} = $columns[5]; for my $lvrecord (run_system_command("lslv $logical_volume{name}")) { chomp $lvrecord; $lvrecord =~ s/^\s+|\s+$//g; next unless $lvrecord; if ( $lvrecord =~ /PERMISSION/i) { my @col=split /\s+/,$lvrecord; if ($col[4] =~ /write/i) { $logical_volume{access} = "READ_WRITE"; } else { $logical_volume{access} = "READ"; } } if ( $lvrecord =~ /STRIPE\sSIZE/i) { my @col=split /\s+/,$lvrecord; $logical_volume{configuration} = "stripes - $col[2]"; } if ($lvrecord =~ /^LPs:/) { if ($lvrecord =~ /PPs:/) { my @col=split /\s+/,$lvrecord; $logical_volume{pps} = $col[3]; } } if ($lvrecord =~ /PP\sSIZE/i) { my @col=split /\s+/,$lvrecord; $logical_volume{ppsize} = $col[5]; if ($col[6] =~ /megabyte/i) { $logical_volume{ppsize} *= 1048576 ; } if ($col[6] =~ /kilobyte|kb/i) { $logical_volume{ppsize} *= 1024; } } } $logical_volume{sizeb} = $logical_volume{ppsize} * $logical_volume{pps} if $logical_volume{ppsize} and $logical_volume{pps}; $logical_volume{sizeb} = 0 unless $logical_volume{sizeb}; $logical_volume{configuration} = 'CONCAT' unless $logical_volume{configuration}; if ($logical_volume{status} =~ /open/i) { $logical_volume{status} = "OPENED"; $logical_volume{status} = "$logical_volume{status}_$logical_volume{access}" if ($logical_volume{access}); } else { $logical_volume{status} = "CLOSED"; } # Physical entities used by the volume push @{$logical_volume{child_entity_criteria}}, { volume_group => $volume_group{name}, product => $volume_group{product}, entity_type => 'Physical Entity', volume_name => $logical_volume{os_identifier} }; push @aixlvmarray,\%logical_volume; } } return \@aixlvmarray; } #------------------------------------------------------------------------------ # FUNCTION : getVolumeMetrics # # DESC # return a array of hashes for all volume manager metrics # # ARGUMENTS # #------------------------------------------------------------------------------- sub get_veritas_volume_metrics ( ) { # Not yet implemented for HPUX # It is a dummy function as of now return ; } #------------------------------------------------------------------------------------ # FUNCTION : get_filesystem_metrics # # # DESC # Returns a array of hashes of filesystem metrics # # ARGUMENTS: # # #----------------------------------------------------------------------------- sub get_filesystem_metrics ( ) { return \@storage::Register::filesystemarray if @storage::Register::filesystemarray; my %fsarray; my %emfiles; # Hash for the files. my @filesys ; @filesys = storage::Utilities::getConfig("FileSystems"); my @cnt = storage::Utilities::getConfig("Collection Size"); # Get the Filesystem limit from the config file. Maximum # number of filesystems to delete my $temp; my $cnt_obj; my $fs_cnt = 100; for my $res (@cnt) { ($temp , $cnt_obj) = split(/=/,$res) ; if ($temp =~ /Filesystem/i) { $fs_cnt=$cnt_obj; last; } } foreach my $file (@filesys) { chomp $file; # Skip Blank Lines next unless $file; $file =~ s/^\s+|\s+$//g; $emfiles{$file} = $file; } # -P df information in portable format, Gives out in block size of 512 bytes # Build a hash of the filesystem information on keys filesystem type # and mount point # Execute command twice, bug in df leaves out some nfs file systems # the first time # Fix for bug 6002107, hang with df -P. If the commad fails then # continue with the next dont exit my @dummy = run_system_command("df -P",120,1,1); my @file_rows = run_system_command("nmhs run_sysv_df -n"); storage::Utilities::setConfig("FileSystems",1); my $fs_proc = 0; for my $fsdata (@file_rows) { if ($fs_proc == $fs_cnt) { if (!(keys(%emfiles))) { storage::Utilities::setConfig("FileSystems",0); storage::Register::log_error_message("The number of File Systems to be monitored is larger than $fs_cnt. Please add the File Systems to be monitored inthe config file emagent_storage.config"); } last; } chomp $fsdata; $fsdata =~ s/^\s+|\s+$//g; next unless $fsdata; my @col=split /:/,$fsdata; my $mnt = $col[0]; my $type = $col[1]; $type =~ s/^\s+|\s+$//g; $mnt =~ s/^\s+|\s+$//g; # Filter the files based on the config file read. # for nfs Split the server name and file system ( my $nfs_serv, my $exported_filesystem ) = ( $mnt =~ /^\s*([^:]*)\s*:\s*(.+)\s*$/ ) if $mnt =~ /^([^:]*):(.+)$/; if ($nfs_serv) { next if ((keys (%emfiles) > 0) && ($emfiles{$mnt} ne $mnt) && ($emfiles{$nfs_serv} ne $nfs_serv)); } else { next if ((keys (%emfiles) > 0) && ($emfiles{$mnt} ne $mnt)); } $type = 'nfs' if $type =~ /($storage::Register::config{filesystem}{nfsfstypes})/; next if $type =~ /^($storage::Register::config{filesystem}{skipfilesystems})$/i; for my $fsrec (run_system_command("df -Pk $mnt",120,1,1)) { last if ($fs_proc == $fs_cnt); my %fsinfo = (); chomp $fsrec; $fsrec =~ s/^\s+|\s+$//g; next unless $fsrec; next if $fsrec =~ /^(Filesystem)/i; my @col=split /\s+/,$fsrec; $fsinfo{filesystem} = $col[0]; $fsinfo{size} = $col[1] * 1024; $fsinfo{used} = $col[2] * 1024; $fsinfo{free} = $col[3] * 1024; $fsinfo{fstype} = $type; $fsinfo{mountpoint} = $col[5]; ( $fsinfo{nfs_server}, $fsinfo{nfs_exported_filesystem} ) = ( $fsinfo{filesystem} =~ /^\s*([^:]*)\s*:\s*(.+)\s*$/ ) if $fsinfo{fstype} eq 'nfs' and $fsinfo{filesystem} =~ /^([^:]*):(.+)$/; push @{$fsarray{$fsinfo{fstype}}},\%fsinfo; $fs_proc++; } } if ($fs_proc < $fs_cnt) { for my $fsrec (run_system_command("lsps -a")) { if ($fs_proc == $fs_cnt) { if (!(keys(%emfiles))) { storage::Utilities::setConfig("FileSystems",0); storage::Register::log_error_message("The number of File Systems to be monitored is larger than $fs_cnt. Please add the File Systems to be monitored inthe config file emagent_storage.config"); } last; } my %fsinfo = (); chomp $fsrec; $fsrec =~ s/^\s+|\s+$//g; next unless $fsrec; next if $fsrec =~ /^(Page)/i; my @col=split /\s+/,$fsrec; $fsinfo{filesystem} = "/dev/$col[0]"; # Filter the files based on the config file read. next if ((keys (%emfiles) > 0) && ($emfiles{$fsinfo{filesystem}} ne $fsinfo{filesystem})); ( $fsinfo{size} ) = ($col[3] =~ /(\d+)/); $fsinfo{size} = $fsinfo{size} * 1024 * 1024; $fsinfo{used} = $fsinfo{size}; $fsinfo{free} = 0; $fsinfo{fstype} = "swap"; push @{$fsarray{$fsinfo{fstype}}},\%fsinfo; $fs_proc++; } } my %nfsservers; # For each file system type for my $fstype( keys %fsarray ) { #------------------------------------------------------- # Build the nfs server list and server information #------------------------------------------------------- if ( $fstype eq 'nfs' ) { # build Unique list of nfs servers for fstype = nfs, # filesystem for nfs is server:filesystem %nfsservers = map{$_->{nfs_server} => 1 if $_->{nfs_server} } @{$fsarray{$fstype}}; #Get the identifier for each of the nfs server , build a #hash of hashes for nfs configuration # NOTE: AIX support for get_server_identifier to be done map {my %reslt = storage::sUtilities::get_server_identifier($_); $nfsservers{$_} = \%reslt; } keys %nfsservers; } for my $fsref ( @{$fsarray{$fstype}} ) { my %nfs; my %mountpoint; my %filesystem; # Get the nfs(vendor,product,server) hash if filesystem # Note : mount privilege to be done for AIX $fsref->{nfs_mount_privilege} = storage::sUtilities::get_mount_privilege($fsref->{mountpoint}) if $fsref->{fstype} eq 'nfs' and $fsref->{mountpoint}; $fsref->{nfs_server_net_interface_address} = $nfsservers{$fsref->{nfs_server}}->{nfs_server_net_interface_address} if $fsref->{fstype} eq 'nfs' and $fsref->{nfs_server} and $nfsservers{$fsref->{nfs_server}} and $nfsservers{$fsref->{nfs_server}}->{nfs_server_net_interface_address}; $fsref->{nfs_server_ip_address} = $nfsservers{$fsref->{nfs_server}}->{nfs_server_ip_address} if $fsref->{fstype} eq 'nfs' and $fsref->{nfs_server} and $nfsservers{$fsref->{nfs_server}} and $nfsservers{$fsref->{nfs_server}}->{nfs_server_ip_address}; # Create the mozart metrics that are required # The mountpoint storage entity if there is a mountpoint if ( $fsref->{mountpoint} ) { $mountpoint{storage_layer} = 'LOCAL_FILESYSTEM'; $mountpoint{entity_type} = 'Mountpoint'; $mountpoint{key_value} = $fsref->{mountpoint}; $mountpoint{os_identifier} = $fsref->{mountpoint}; $mountpoint{sizeb} = $fsref->{size}; $mountpoint{usedb} = $fsref->{used}; $mountpoint{freeb} = $fsref->{free}; $mountpoint{filesystem_type} = $fsref->{fstype}; $mountpoint{filesystem} = $fsref->{filesystem}; $mountpoint{mountpoint} = $fsref->{mountpoint}; $mountpoint{name} = $fsref->{mountpoint}; # Extra metric columns for NFS if ( $fsref->{fstype} eq 'nfs' ) { $mountpoint{storage_layer} = 'NFS'; # Copy all the nfs_fields for my $nfskey ( keys %{$fsref} ) { next unless $nfskey =~ /^nfs_/; next unless $fsref->{$nfskey}; $mountpoint{$nfskey} = $fsref->{$nfskey}; } } push @storage::Register::filesystemarray,\%mountpoint; } $filesystem{key_value} = $fsref->{filesystem}; $filesystem{sizeb} = $fsref->{size}; $filesystem{usedb} = $fsref->{size}; $filesystem{filesystem_type} = $fsref->{fstype}; $filesystem{filesystem} = $fsref->{filesystem}; $filesystem{name} = $fsref->{filesystem}; $filesystem{os_identifier} = $fsref->{filesystem} if $fsref->{fstype} ne 'nfs' and -e $fsref->{filesystem}; $filesystem{mountpoint} = $fsref->{mountpoint} if $fsref->{mountpoint}; # Who are its parents # The current mountpoint # Since these are OS entities any other cached filesystem mounts or # filesystem based swap will be discovered by the analysis program # There is no need to define the parent key criteria for these $filesystem{parent_key_value} = $mountpoint{key_value} if $fsref->{mountpoint} and $mountpoint{mountpoint}; $filesystem{storage_layer} = 'LOCAL_FILESYSTEM'; $filesystem{entity_type} = 'Filesystem'; # If the filesystem is a regular file or directory not a block device then its a file my $fs_file_type = storage::Register::get_file_type( $filesystem{os_identifier} ) if $filesystem{os_identifier}; $filesystem{entity_type} = 'File' if $fs_file_type and $fs_file_type =~ /_REGULAR/i; $filesystem{entity_type} = 'Directory' if $fs_file_type and $fs_file_type =~ /_DIRECTORY/i; # Extra metric columns for NFS if ( $fsref->{fstype} eq 'nfs' ) { $filesystem{storage_layer} = 'NFS'; $filesystem{entity_type} = 'Filesystem'; # copy all the nfs_ fields for my $nfskey ( keys %{$fsref} ) { next unless $nfskey =~ /^nfs_/; next unless $fsref->{$nfskey}; $filesystem{$nfskey} = $fsref->{$nfskey}; } # Generate a default global unique id for the server based on the # server identification obtained # if post processing cannot find a matching server this can be used if ( $filesystem{nfs_server_net_interface_address} ) { $filesystem{global_unique_id} = "$filesystem{nfs_server_net_interface_address}::$filesystem{filesystem}"; } elsif ( $filesystem{nfs_server_ip_address} ) { $filesystem{global_unique_id} = "$filesystem{nfs_server_ip_address}::$filesystem{filesystem}"; } elsif ( $filesystem{nfs_server} ) { $filesystem{global_unique_id} = "$filesystem{nfs_server}::$filesystem{filesystem}"; } else { my $target_id = get_target_id(); $filesystem{global_unique_id} = "no_gid::$target_id::$filesystem{filesystem}" if $target_id; } $filesystem{global_unique_id} = "no_targetid::$filesystem{filesystem}" unless $filesystem{global_unique_id}; } push @storage::Register::filesystemarray,\%filesystem; } } return \@storage::Register::filesystemarray; } #------------------------------------------------------------------------------- # FUNCTION : runShowmount # # # DESC # run showmount # # ARGUMENTS: # #------------------------------------------------------------------------------ sub runShowmount ( $ ) { return run_system_command("showmount -a $_[0]",120); } #----------------------------------------------------------------------------- # FUNCTION : AUTOLOAD # # DESC # If sub is not defined here then look for it in sUtilities.pm # # ARGUMENTS # Args to be passed to the sub # #---------------------------------------------------------------------------- sub AUTOLOAD { my ( @args ) = @_; my $sub = $AUTOLOAD; $sub =~ s/.*:://; my $sub_path = "storage::sUtilities::$sub"; my $sub_ref = \&$sub_path; return &$sub_ref(@args); } 1; #-----------------------------------------------------------------