Edit D:\app\Administrator\product\11.2.0\dbhome_1\sysman\admin\scripts\provisioning\sampledirectives\hwInfo.pl
use Net::Domain qw(hostfqdn); use strict; ################################################################################ # printHWInfo # sub routine to print information about hardware on current host (required for # rac provisioning) in simple xml form. ################################################################################ sub printHWInfo { print "<hwInfo>"; print "<hostName name=\"".hostfqdn()."\" />"; &printDiskInfo; &printNICInfo; &printDriveLetterInfo; print "</hwInfo>"; } ################################################################################ # printDiskInfo # sub routine to print disk information in simple xml form. ################################################################################ sub printDiskInfo() { # get list of disks. my @diskpartOutput = &getDiskpartOutput ("list disk"); return if (scalar(@diskpartOutput) < 1); # get output as records. my @disks = &getOutputRecords ($diskpartOutput[0]); return if (scalar(@disks) == 0); print "<disks>"; # output elements are in form (Disk|Status|Size|Free|Dyn|Gpt) # get partition info for each disk. foreach (@disks) { # get partition list in disk. my @diskInfo = split /\|/; next if ($diskInfo[4] ne ""); # we're not interested in dynamic disks. # we have a non-dynamic disk here. my $disk = $diskInfo[0]; # get disk details. @diskpartOutput = &getDiskpartOutput ("select $disk", "detail disk"); next if (scalar(@diskpartOutput) < 2); # process output of second command. my $diskDetails = $diskpartOutput[1]; # get disk id from output. my ($diskID) = ($diskDetails =~ /.*?\s+id\s*:(.*?)\n.*/i); $diskID =~ s/^\s+//; $diskID =~ s/\s+$//; # print disk info. my $freeSpaceInDisk = &getSizeInMB ($diskInfo[3]); my $diskNum = (split(/\s+/, $disk))[1]; print "<disk" . " id=\"$diskID\"" . " number=\"$diskNum\"" . " freeSpace=\"$freeSpaceInDisk\"" . ">"; # get partition info. @diskpartOutput = &getDiskpartOutput ("select $disk", "list partition"); if (scalar(@diskpartOutput) < 2) { print "</disk>"; next; } # get output of second command as records. my @partitions = &getOutputRecords ($diskpartOutput[1]); # xml for partitions. my $partitionXML = ""; my $decrement = 0; # output elements are in form (Partition|Type|Size|Offset) foreach (@partitions) { my @partitionInfo = split /\|/; if ($partitionInfo[1] !~ /logical/i) { # this is not a logical partition. # there is ideally only one 'non-logical' partition # (the extended partition itself) $decrement++; next; } # ok, a logical partition. let us obtain details for this. my $partition = $partitionInfo[0]; # get details. my $partitionSize = &getSizeInMB ($partitionInfo[2]); @diskpartOutput = &getDiskpartOutput ("select $disk", "select $partition", "detail partition"); next if (scalar(@diskpartOutput) < 3); # get output of third command as records. my @partitionDetails = &getOutputRecords ($diskpartOutput[2]); # output elements are in form # (Volume|Ltr|Label|Fs (format)|Type (logical etc)|Size|Status|Info) next if (scalar (@partitionDetails) == 0); # no detailed info available. # get fields. my @details = split (/\|/, $partitionDetails[0]); # correct partition number is the sequential logical-partition number # (extended-partition number must not be considered) my $partitionNum = (split(/\s+/, $partition))[1] - $decrement; my $driveLtr = $details[1]; $driveLtr = "$driveLtr:" if ($driveLtr ne ""); my $formatType = $details[3]; # add partition info # (PartitionNum, Size (in MB), FormatType, DriveLtr). print "<partition" . " number=\"$partitionNum\"" . " size=\"$partitionSize\"" . " formatType=\"$formatType\"" . " driveLetter=\"$driveLtr\"" . " />"; } # end partition loop. # end disk info. print "</disk>"; } # end disk loop. print "</disks>"; } ################################################################################ # printNICInfo # sub routine to print information about NICs on current host in simple xml # form. ################################################################################ sub printNICInfo { my $cmdOutput; { local $/; undef $/; my $netShExe = $ENV{'systemroot'}."\\system32\\netsh.exe"; die "Could not find netsh executable" if (! -e $netShExe); open (IN, "$netShExe interface ip show address |") or die "Cannot read netsh output: $?"; $cmdOutput = <IN>; close IN; } my @interfaces = split("\n{2,}", $cmdOutput); return if (scalar(@interfaces) == 0); print "<interfaces>"; foreach (@interfaces) { my ($interfaceName, $ipAddr, $subnetMask) = (/"(.*)".*?IP.*?:(.*?)\n.*?SubnetMask.*?:(.*?)\n.*/is); # trim values. $interfaceName =~ s/^\s+//; $interfaceName =~ s/\s+$//; $ipAddr =~ s/^\s+//; $ipAddr =~ s/\s+$//; $subnetMask =~ s/^\s+//; $subnetMask =~ s/\s+$//; # replace special characters in interface name (& < > " '). $interfaceName =~ s/&/&/g; $interfaceName =~ s/</</g; $interfaceName =~ s/>/>/g; $interfaceName =~ s/"/"/g; $interfaceName =~ s/'/'/g; # get subnet using ipaddr and subnet mask. my @ipAddrArr = split("\\\.", $ipAddr); my @subnetMaskArr = split("\\\.", $subnetMask); my @subnetArr; for (my $i = 0; $i <= $#ipAddrArr; $i++) { push (@subnetArr, (int($ipAddrArr[$i]) & $subnetMaskArr[$i])); } my $subnet = join(".", @subnetArr); print "<interface" . " name=\"$interfaceName\"" . " ipAddress=\"$ipAddr\"" . " subnet=\"$subnet\"" . " />"; } print "</interfaces>"; } ################################################################################ # printDriveLetterInfo # sub routine to print out information about used / available drive letters on # this host (printed as XML element with comma-separated drive letters). ################################################################################ sub printDriveLetterInfo { # 1. get local drive info using diskpart. my @diskpartOutput = &getDiskpartOutput ("list volume"); return if (scalar(@diskpartOutput) < 1); # get output as records. my @volumes = &getOutputRecords ($diskpartOutput[0]); return if (scalar(@volumes) == 0); # output elements are in form (Volume|DriveLtr|Label|Fs|Type|Size|Status|Info) # retrieve used letters. my %count; foreach (@volumes) { # get drive letter for volume. my @volumeInfo = split /\|/; my ($driveLetter) = uc ($volumeInfo[1]); if ($driveLetter =~ /(.*):/i) { # remove trailing characters, if any. $driveLetter = $1; } # set count for this letter. $count{$driveLetter} = 1 if ($driveLetter ne ""); } # 2. retrieve mapped drive info using 'net use'. my $netExe = $ENV{'systemroot'}."\\system32\\net.exe"; die "Could not find net executable" if (! -e $netExe); open (NETUSE, "$netExe use |") or die "Cannot parse mapped drive information."; # read output of above command. my @output; @output = <NETUSE>; close NETUSE; # get mapped drive letters. foreach (@output) { $count{uc($1)} = 1 if (/.*?\s*([A-Za-z]):\s*.*?/i); } # 3. assign used / available drive letters. my @usedDriveLetters; my @availableDriveLetters; foreach ('A'..'Z') { my $driveLtr = "$_:"; if ($count{$_} == 1) { push (@usedDriveLetters, $driveLtr); } else { push (@availableDriveLetters, $driveLtr); } } # 4. print necessary info. print "<driveLetters" . " usedLetters=\"" . join(",", sort(@usedDriveLetters)) . "\" availableLetters=\"" . join(",", sort(@availableDriveLetters)) . "\" />"; } ################################################################################ # getDiskpartOutput # sub routine to retrieve output for a diskpart command. # param : the diskpart command. # return: an array representing all non-blank lines of output for the given cmd. # in case of multiple commands, the individual outputs are separated # by blank lines. ################################################################################ sub getDiskpartOutput { my (@diskpartCmds) = @_; my $tmp = $ENV{TEMP}; # temporary location. if ($tmp eq "") { $tmp = $ENV{TMP}; } if ($tmp eq "") { $tmp = "C:\\temp"; } my $tmpFile = "$tmp\\$$.out"; # for storing output. # execute diskpart. my $diskpartExe = $ENV{'systemroot'}."\\system32\\diskpart.exe"; die "Could not find diskpart executable" if (! -e $diskpartExe); open (DISKPART, "| $diskpartExe > $tmpFile") or die "Cannot execute diskpart utility: $?"; foreach my $diskpartCmd (@diskpartCmds) { print DISKPART "$diskpartCmd\n"; } print DISKPART "exit\n"; close DISKPART; # read output for the command executed. my $cmdOutput; { local $/; undef $/; open (IN, $tmpFile) or die "Cannot read diskpart output: $?"; $cmdOutput = <IN>; close IN; unlink ($tmpFile); } my $prompt = "DISKPART>"; # only store output between first and last prompts. $cmdOutput =~ s/.*?$prompt(.*)$prompt.*/$1/is; # trim output of blank lines. $cmdOutput =~ s/^\s*\n//gs; # from start. $cmdOutput =~ s/\n\s*$//gs; # from end. $cmdOutput =~ s/\n\s*\n/\n/gs; # from between. # return output as an array (outputs are separated by prompts). return split(/\n\s*?$prompt\s*?\n/, $cmdOutput); } ################################################################################ # getOutputRecords # sub routine to retrieve records from the output of a diskpart command. # param : the output as a string. # return: an array, with each element representing fields in the output list. # the fields in the records are separated by a pipe (|). ################################################################################ sub getOutputRecords { my ($output) = @_; my @outArr = split("\n", $output); # get position of end of header. my $headerEndPos = &getHeaderEndIndex(@outArr); if ($headerEndPos == -1) { # no such output. @outArr = (); return @outArr; } # end of header represents field positions. so get field positions. my @fieldPosArr = &getFieldPositions($outArr[$headerEndPos]); # chop header from output. splice (@outArr, 0 , $headerEndPos + 1); for (my $i = 0; $i <= $#outArr; $i++) { my @out; # temporary array to hold fields. for (my $j = 0; $j <= $#fieldPosArr; $j+=2) { # obtain field, trim it and add it to array. my $field = substr($outArr[$i], $fieldPosArr[$j], $fieldPosArr[$j+1]); $field =~ s/^\s+//; $field =~ s/\s+$//; push(@out, $field); } # separate fields with a pipe. $outArr[$i] = join("|", @out); } return @outArr; } ################################################################################ # getHeaderEndIndex # sub routine to retrieve end of header for a diskpart command output. # param : the diskpart command output as an array (one element = one o/p line). # return: the index of element representing the end of header, # -1 if there is no header. ################################################################################ sub getHeaderEndIndex { my (@disks) = @_; for (my $i = 0; $i <= $#disks; $i++) { return $i if ($disks[$i] =~ /^\s*(\s+\-+)*\s*$/); } return -1; } ################################################################################ # getFieldPositions # sub routine to compute starting positions and lengths of fields in a tabular # diskpart output. # param : a reference string consisting of '-'s representing fields and spaces # for the gaps between fields. # return: an array of pairs of elements representing offset / length of each # field in the output. ################################################################################ sub getFieldPositions { my ($refStr) = @_; my @posArr; # field begins at '-' and ends before ' '. my $start = index($refStr, "-"); my $end = index($refStr, " ", $start) if ($start != -1); while ($start != -1) { push(@posArr, $start); push(@posArr, $end - $start); $start = index($refStr, "-", $end); if ($start != -1) { $end = index($refStr, " ", $start); if ($end == -1) { # make 'end' point to one element after all the '-'s. for ($end = $start; $end <= length($refStr) && substr($refStr, $end, 1) == "-"; $end++) {} } } } return @posArr; } ################################################################################ # getSizeInMB # sub routine to return the size in MB, given a size string. # param : a string in the form 'size unit'. where 'unit' is B, KB, MB or GB. # return: the size, converted to MB. ################################################################################ sub getSizeInMB { my ($sizeStr) = @_; my ($size, $unit) = split (/\s+/, $sizeStr); return $size if ($size eq "" || $size == 0); if ($unit !~ /mb/i) { $size = "$size.0"; if ($unit =~ /^b$/i) { $size = $size / 1000000; } elsif ($unit =~ /^kb$/i) { $size = $size / 1000; } elsif ($unit =~ /^gb$/i) { $size = $size * 1000; } } return $size; } ############################# end of sub routines ############################## &printHWInfo;
Ms-Dos/Windows
Unix
Write backup
jsp File Browser version 1.2 by
www.vonloesch.de