# S402ASM.def: Collects Automatic Storage Management Information # $Id: S402ASM.def,v 1.46 2009/08/28 15:07:15 mschenke Exp $ # ARCS: $Header: /u02/webapps/workbench/cvs/RDA_4/src/scripting/lib/modules/S402ASM.def,v 1.46 2009/08/28 15:07:15 mschenke Exp $ # # Change History # 20090827 DEM Fix duplicate devices. =head1 NAME S402ASM - Collects Automatic Storage Management Information =head1 DESCRIPTION This module collects Automatic Storage Management information (Oracle Database 10g). This module must be run as SYSDBA to collect the whole information. The following reports can be generated and are regrouped under C: =cut echo tput('bold'),'Processing ASM module ...',tput('off') # Initialization var $ORACLE_HOME = getSetting('ASM_ORACLE_HOME','') var $ORACLE_SID = getSetting('ASM_ORACLE_SID','+ASM') var $ALERT_TEXT = getSetting('ASM_ALERT_TEXT',0) var $ADVANCED = getSetting('ASM_ADVANCED') var $DISTINCT_HOME = getSetting('ASM_DISTINCT_HOME',0) var $BDUMP_MAX = getSetting('ASM_TRACE_BDUMP',2) var $UDUMP_AGE = getSetting('ASM_TRACE_UDUMP',0) var $LOG_AGE = getSetting('ASM_TRACE_AGE',15) var $LOG_ERRORS = max(1,getSetting('ASM_TRACE_ERRORS',250)) var $LOG_TRESHOLD = getSetting('ASM_TRACE_TRESHOLD',20480) var $LOG_RATIO = max(1,getSetting('ASM_TRACE_RATIO',10)) var $LOG_VOLUME = getSetting('ASM_TRACE_VOLUME',10) var $SQL_LOGIN = uc(getSetting('ASM_LOGIN','/')) var $OSN = getOsName() var $TOC = '%TOC%' var $TOP = '[[#Top][Back to top]]' toc '1:ASM' # Load the libraries run DBinfo() run INSTinfo() run library() # Auto detect the ASM_ORACLE_SID and ASM_ORACLE_HOME in a cluster if compare('eq',$ORACLE_SID,'*') {# If ORA_CRS_HOME environment variable is not set, find it if possible var $ORA_CRS_HOME = getEnv('ORA_CRS_HOME') if !testDir('d',$ORA_CRS_HOME) {if match($OSN,'solaris') {if grepFile('/etc/init.d/init.cssd','^ORA_CRS_HOME=','f') var $ORA_CRS_HOME = value(last) } elsif match($OSN,'hpux') {if grepFile('/sbin/init.d/init.cssd','^ORA_CRS_HOME=','f') var $ORA_CRS_HOME = value(last) } elsif match($OSN,'aix') {if grepFile('/etc/init.cssd','^ORA_CRS_HOME=','f') var $ORA_CRS_HOME = value(last) } elsif match($OSN,'dec_osf') {if grepFile('/sbin/init.d/init.cssd','^ORA_CRS_HOME=','f') var $ORA_CRS_HOME = value(last) } elsif match($OSN,'linux') {if grepFile('/etc/init.d/init.cssd','^ORA_CRS_HOME=','f') var $ORA_CRS_HOME = value(last) } elsif isWindows() {var $key = 'HKLM\SYSTEM\CurrentControlSet\Services\OracleCRService' if match(getRegValue($key,'ImagePath'),'^(.*)\s+service\s*$',true) {var @tbl = splitDir(dirname(catFile(trim(last)))) var $tbl[-1] = curDir() var $ORA_CRS_HOME = catDir(@tbl) } } } # Detect the parameters if testDir('d',$ORA_CRS_HOME) {var ($flg,$ORACLE_SID) = (true,'+ASM') # First try to resolve both parameters if grepCommand(concat(catCommand($ORA_CRS_HOME,'bin','srvctl'),\ ' config asm -n ',quote(getSetting('MACHINE_NAME'))),\ '^(PRK[A-Z]\-\d{4}|\s*\[)','v') {var ($lin) = last var ($sid,$dir) = split('\s+',$lin,2) if testDir('d',catDir($dir)) {var ($flg,$ORACLE_SID,$ORACLE_HOME) = (false,$sid,lastDir()) debug ' Inside ASM module, auto-detecting home:',$ORACLE_HOME debug ' Inside ASM module, auto-detecting SID:',$ORACLE_SID } } # Next try to resolve Oracle SID if $flg {var $pat = concat('\.',quote(getSetting('MACHINE_NAME')),'\.([^\.]+)\.asm$') loop $lin (grepCommand(catCommand($ORA_CRS_HOME,'bin','crs_stat'),'\.asm$')) {if match($lin,$pat) {var $ORACLE_SID = concat('+',last) debug ' Inside ASM module, auto-detecting SID:',$ORACLE_SID break } } } } } # Change the database context var $sid = setSqlSid($ORACLE_SID) var $try = setSqlFailure(0) if compare('eq',$SQL_LOGIN,'/') var $old = setSqlLogin('@ AS SYSDBA','') else {if hasSqlPassword($usr,$sid) var $pwd = undef else var $pwd = askPassword(concat('Enter ',$SQL_LOGIN,'@',$ORACLE_SID,\ ' user password:')) var $old = setSqlLogin(concat($SQL_LOGIN,'@ AS SYSDBA'),$pwd) } if $DISTINCT_HOME {var $env = setEnv('ORACLE_HOME',$ORACLE_HOME) =head2 product_info - ASM Product Information Gathers the ASM product information if ASM is installed in a separate Oracle Home. =cut debug ' Inside ASM module, processing Product Information (can take time)' report product_info write '---+!! ASM Oracle Home Product Information' write $TOC write '---+ Files in Oracle Home' call statDir('an',$ORACLE_HOME) write $TOP var $fil = catFile($ORACLE_HOME,'inventory','ContentsXML','comps.xml') if testFile('fr',$fil) call inventory_details($fil,getSetting('ASM_INTERIM')) toc '2:[[',getFile(),'][rda_report][Product Information]]' } =head2 init_ora - INIT.ORA Determines if the spfile is used. RDA connects to the database and looks for a value coming from the spfile parameter. If a value is found, RDA does not search for F. A select for C is executed to determine whether to skip the search for F. =cut debug ' Inside ASM module, processing INIT.ORA' report init_ora set $sql {SELECT '|' || p.name || '|' || p.value || '|' " FROM v$parameter p " WHERE p.name = 'spfile' " AND p.value IS NOT NULL; } call loadSql($sql) var $NO_SQL = grepLastSql('^ORA-01034:','f') var $SPFile_In_Use = grepLastSql('\|spfile\|','f') if $SPFile_In_Use write 'SPFile appears to be in use on this server%BR%\ Review "V$Parameters" and "Database SPFile Parameters" links \ for parameter settings.' elsif getSetting('ASM_PFILE_LOCAL') {if getSetting('ASM_PFILE_LOCATION') var $fil = replace(last,'\*',$ORACLE_SID) else {if isWindows() var $dir = catDir($ORACLE_HOME,'database') else var $dir = catDir($ORACLE_HOME,'dbs') var ($fil) = grepDir($dir,concat('^init',quote($ORACLE_SID),'\.ora$'),'p') } if $fil {var %treated = () prefix {write '---+!! INIT.ORA Information' write $TOC write '---+ Contents of INIT.ORA ',encode($fil) } if writeFile($fil) {write $TOP # Extract the IFILE, ignoring comments in the Oracle supplied INIT.ORA var $treated{$fil} = 1 while value(grepFile($fil,'^[^#]*ifile','fi')) {var $fil = trim(last) var $fil = replace($fil,"'",'',true) var $fil = replace($fil,'\?',$ORACLE_HOME) var $fil = replace($fil,'\$ORACLE_HOME',$ORACLE_HOME) var $fil = replace($fil,'\${ORACLE_HOME}',$ORACLE_HOME) var $fil = replace($fil,'%ORACLE_HOME%',$ORACLE_HOME) break exists($treated{$fil}) write '---+ Contents of IFILE ',encode($fil) call writeFile($fil) write $TOP var $treated{$fil} = 1 } } else {unprefix write encode($fil),' is not readable or does not exist.%BR%\ File permissions are as follows:%BR%' call statFile('b',$fil) write '%BR%User: ',id(),'%BR%' } } else write 'INIT.ORA not located on this server.' } toc '2:[[',getFile(),'][rda_report][INIT.ORA]]' =head2 vspparameters - SPFile Parameters Gets C information. =cut if !$NO_SQL {debug ' Inside ASM module, processing V$SPParameter' debug ' SPFile_In_Use is ',$SPFile_In_Use report vspparameters if $SPFile_In_Use {write '---+!! SPFile Parameter Values' write '|*SID*|*Name*|*Value*|*Is Specified?*| *Ordinal*|*Update Comment*|' set $sql {SELECT '|' || " s.sid || '|' || " s.name || '|' || " NVL(s.value, ' ') || '|' || " s.isspecified || '| ' || " s.ordinal || '|' || " NVL(s.update_comment, ' ') || '|' " FROM v$spparameter s " ORDER BY s.name, s.sid; } call writeSql($sql) if getSqlMessage() write last,'%BR%' } else {write '---+!! SPFile Parameter Values' write 'This database instance is not using an spfile.' } if isCreated() toc '2:[[',getFile(),'][rda_report][SPFile Parameters]]' =head2 vparameters - V$Parameters Gets C information. =cut debug ' Inside ASM module, processing V$Parameter' report vparameters var $TTL = undef var @TTL = ('',\ '---+!! Automatic Storage Management Parameters') var @HDR = ('',\ '|*Parameter Name*|*Value*|*Default*|*Modified*|') set $sql {SELECT '|' || " SUBSTR(name, 0, 512) || '|' || " NVL(SUBSTR(value, 0, 512), '%NULL%') || '|' || " isdefault || '|' || " ismodified || '|' " FROM v$parameter " ORDER BY name; } call separator(1) call writeSql($sql) call separator(0,'V$Parameters') =head2 overview - Overview Extracts the ASM information from the database. =cut debug ' Inside ASM module, gathering overview information' report overview var $TTL = '---+!! Automatic Storage Management Overview' if $ADVANCED {var @TTL = ('',\ '---+ Disk Groups',\ '---+ Partner Information',\ '---+ Robust Disk Information',\ '---+ ASM Attribute Information') var @HDR = ('',\ '| *Grp*|*Name*|*State*|*Type*| *Total MiB*| *Free MiB*|',\ '| *Grp*| *Disk*| *number_kfdpartner*| *parity_kfdpartner*| \ *active_kfdpartner*|',\ '| *Group Number*| *Disk Number*| *Incarnation*|*Mount Status*|\ *Header Status*|*Mode Status*|*State*|*Library*| *Total MiB*| \ *Free MiB*|*Name*|*FailGroup*|*Label*|*Path*|*Create Date*|\ *Mount Date*| *Reads*| *Writes*| *Read Errs*| *Write Errs*|\ *Read Time*|*Write Time*| *Bytes Read*| *Bytes Written*|',\ '|*Name*|*Value*|') set $sql {SELECT '| ' || " group_number || '|' || " name || '|' || " state || '|' || " type || '| ' || " total_mb || '| ' || " free_mb || '|' " FROM v$asm_diskgroup; "PROMPT ___Macro_separator(2)___ "SELECT '| ' || " grp || '| ' || " disk || '| ' || " number_kfdpartner || '| ' || " parity_kfdpartner || '| ' || " active_kfdpartner || '|' " FROM x$kfdpartner; "PROMPT ___Macro_separator(3)___ "SELECT '[[[' || CHR(10) || '| ' || " group_number || '| ' || " disk_number || '| ' || " incarnation || '|' || " mount_status || ' |' || " header_status || ' |' || " mode_status || ' |' || " state || ' |' || " library || ' | ' || " total_mb || '| ' || " free_mb || '| ' || " name || '| ' || " failgroup || ' |' || " label || ' |' || " path || ' |' || " TO_CHAR(create_date,'DD-Mon-YYYY') || ' |' || " TO_CHAR(mount_date,'DD-Mon-YYYY') || ' | ' || " reads || '| ' || " writes || '| ' || " read_errs || '| ' || " write_errs || '| ' || " read_time || ' | ' || " write_time || '| ' || " bytes_read || '| ' || " bytes_written || '|' || " CHR(10) || ']]]' " FROM v$asm_disk; } var (undef,$col) = getSqlColumns('RDA','','V$ASM_ATTRIBUTE') call clearSqlColumns('RDA') if $col {append $sql {PROMPT ___Macro_separator(4)___ "SELECT '|' || " name || ' |' || " value || ' |' " FROM v$asm_attribute; } } call separator(1) call writeSql($sql,2) call separator(0,'Overview') # Creating separate datafiles for the long-running queries. prefix write '---+ Allocation Information' suspend overview data kfdat prefix {write '---+ Allocation Information (Disk)' write '| *group_kfdat*| *number_kfdat*| *aunum_kfdat*| *v_kfdat*| \ *fnum_kfdat*| *i_kfdat*| *xnum_kfdat*|*raw_kfdat*|' } set $sql {SELECT '| ' || " group_kfdat || '| ' || " number_kfdat || '| ' || " aunum_kfdat || '| ' || " v_kfdat || '| ' || " fnum_kfdat || '| ' || " i_kfdat || '| ' || " xnum_kfdat || '|' || " raw_kfdat || '|' " FROM x$kfdat; } call writeSql($sql,2) if isCreated() {var $url = getFile('.') resume overview write '|*Disk*|',concat('[[',$url,'][_blank][x$kfdat]]'),'|' suspend overview } data kffxp prefix {write '---+ Allocation Information (ASM File)' write '| *Grp*| *Num*|*Incarn*|*pxn_kffxp*| *xnum_kffxp*| *Lxn*| *Disk*| \ *au_kffxp*| *Flg*| *Chk*|' } set $sql {SELECT '| ' || " group_kffxp || '| ' || " number_kffxp || '|' || " incarn_kffxp || '|' || " pxn_kffxp || '| ' || " xnum_kffxp || '| ' || " lxn_kffxp || '| ' || " disk_kffxp || '|' || " au_kffxp || '| ' || " flags_kffxp || '| ' || " chk_kffxp || '|' " FROM x$kffxp; } call writeSql($sql,2) if isCreated() {var $url = getFile('.') resume overview write '|*ASM File*|',concat('[[',$url,'][_blank][x$kffxp]]'),'|' } else resume overview if hasOutput(true) write $TOP } else {var @TTL = ('',\ '---+ Disk Group Information ',\ '---+ Disk Information',\ '---+ ASM Attribute Information') var @HDR = ('',\ '| *Grp*|*Name*|*State*|*Type*| *Total MiB*| *Free MiB*|',\ '| *Group Number*| *Disk Number*|*Name*|*Mount Status*|\ *Header Status*|*Mode Status*|*State*|*Redundancy*|\ *Failgroup*|*Path*| *Total MiB*| *Free MiB*|',\ '|*Name*|*Value*|') set $sql {SELECT '| ' || " group_number || '|' || " name || '|' || " state || '|' || " type || '| ' || " total_mb || '| ' || " free_mb || '|' " FROM v$asm_diskgroup; "PROMPT ___Macro_separator(2)___ "SELECT '[[[' || CHR(10) || '| ' || " group_number || '| ' || " disk_number || '| ' || " name || '| ' || " mount_status || ' |' || " header_status || ' |' || " mode_status || ' |' || " state || ' |' || " redundancy || ' |' || " failgroup || ' |' || " path || ' |' || " total_mb || ' | ' || " free_mb || '| ' || " CHR(10) || ']]]' " FROM v$asm_disk " WHERE group_number = 1 " ORDER BY group_number,disk_number; } var (undef,$col) = getSqlColumns('RDA','','V$ASM_ATTRIBUTE') call clearSqlColumns('RDA') if $col {append $sql {PROMPT ___Macro_separator(3)___ "SELECT '|' || " name || ' |' || " value || ' |' " FROM v$asm_attribute; } } call separator(1) call writeSql($sql,2) call separator(0,'Overview') } =head2 storage_info - Storage Information Gathers the ASM storage information. =cut debug ' Inside ASM module, gathering storage information' report storage_info var $TTL = '---+!! Storage Information' var @TTL = ('',\ '---+ List of DB clients connected to ASM instance',\ '---+ List of templates',\ '---+ V$ASM_ALIAS Information',\ '---+ V$ASM_DISKGROUP Information',\ '---+ V$ASM_FILE Information',\ '---+ V$ASM_OPERATION Information') var ($HDR[1],$col1) = getSqlColumns('RDA','','V$ASM_CLIENT') call clearSqlColumns('RDA') var ($HDR[2],$col2) = getSqlColumns('RDA','','V$ASM_TEMPLATE') call clearSqlColumns('RDA') if $ADVANCED {var ($HDR[3],$col3) = getSqlColumns('RDA','','V$ASM_ALIAS') call clearSqlColumns('RDA') var ($HDR[4],$col4) = getSqlColumns('RDA','','V$ASM_DISKGROUP') call clearSqlColumns('RDA') var ($HDR[5],$col5) = getSqlColumns('RDA','','V$ASM_FILE') call clearSqlColumns('RDA') var ($HDR[6],$col6) = getSqlColumns('RDA','','V$ASM_OPERATION') call clearSqlColumns('RDA') } if and($col6,$col5,$col4,$col3,$col2,$col1) {set $sql {SELECT :3 " FROM v$asm_alias; "PROMPT ___Macro_separator(1)___ "SELECT :1 " FROM v$asm_client; "PROMPT ___Macro_separator(4)___ "SELECT :4 " FROM v$asm_diskgroup; "PROMPT ___Macro_separator(5)___ "SELECT :5 " FROM v$asm_file; "PROMPT ___Macro_separator(6)___ "SELECT :6 " FROM v$asm_operation; "PROMPT ___Macro_separator(2)___ "SELECT :2 " FROM v$asm_template; } call separator(3) call writeSql(bindSql($sql,$col1,$col2,$col3,$col4,$col5,$col6),2) call separator(0,'Storage Information') } elsif and($col2,$col1) {set $sql {SELECT :1 " FROM v$asm_client; "PROMPT ___Macro_separator(2)___ "SELECT :2 " FROM v$asm_template; } call separator(1) call writeSql(bindSql($sql,$col1,$col2),2) call separator(0,'Storage Information') } =head2 space_info - File/Space Related Information Gathers the File/Space-related information. =cut debug ' Inside ASM module, gathering file/space related information' report space_info var $TTL = '---+!! File/Space Related Information' if $ADVANCED {var @TTL = ('',\ '---+ Files Stored in Diskgroup',\ '---+ Number of Allocation Units per Disk Group',\ '---+ Number of Allocation Units per Diskgroup,Disk',\ '---+ Number of Allocated (V) and Free (F) Allocation Units',\ '---+ Number of AUs per ASM file ordered by AU : Metadata Only',\ '---+ Number of AUs per ASM file ordered by AU : Non Metadata',\ '---+ File Utilization') var @HDR = ('',\ '| *Group Number*| *File Number*|*Full Alias Path*|*File Type*|',\ '| *AU Count*| *DG#*|',\ '| *AU Count*|*Group#,Diskno*|',\ '| *Group#*| *Disk#*|*VF*| *Count*|',\ '| *AU Count*| *File#*| *DG#*|',\ '| *Group Kffxp*| *Number Kffxp*|*Name*| *Count*|',\ '| *Group No*| *File No*| *Bytes*| *Space*| *In MiB*|*Name*|') set $sql {SELECT '| ' || " x.gnum || '| ' || " x.filnum || '|' || " x.full_alias_path || ' |' || " f.ftype || ' |' " FROM (SELECT gnum, " filnum, " CONCAT('+'||gname, sys_connect_by_path(aname, '/')) " full_alias_path " FROM (SELECT g.name gname, " a.parent_index pindex, " a.name aname, " a.reference_index rindex, " a.group_number gnum, " a.file_number filnum " FROM v$asm_alias a, " v$asm_diskgroup g " WHERE a.group_number = g.group_number) " START WITH (MOD(pindex, POWER(2, 24))) = 0 " CONNECT BY PRIOR rindex = pindex) x, " (SELECT group_number gnum, " file_number filnum, " type ftype " FROM v$asm_file " ORDER BY group_number,file_number) f " WHERE x.filnum != 4294967295 " AND x.gnum=f.gnum " AND x.filnum=f.filnum; "PROMPT ___Macro_separator(2)___ "SELECT '| ' || " COUNT(number_kfdat) || '| ' || " group_kfdat || '|' " FROM x$kfdat " GROUP BY group_kfdat; "PROMPT ___Macro_separator(3)___ "SELECT '| ' || " COUNT(*) || '|' || " group_kfdat||','||number_kfdat || ' |' " FROM x$kfdat " GROUP BY group_kfdat,number_kfdat; "PROMPT ___Macro_separator(4)___ "SELECT '| ' || " group_kfdat || '| ' || " number_kfdat || '|' || " v_kfdat || ' | ' || " COUNT(*) || '|' " FROM x$kfdat " GROUP BY group_kfdat, number_kfdat, v_kfdat; "PROMPT ___Macro_separator(5)___ "SELECT '| ' || " COUNT(xnum_kffxp) || '| ' || " number_kffxp || '| ' || " group_kffxp || '|' " FROM x$kffxp WHERE number_kffxp < 256 " GROUP BY number_kffxp, group_kffxp " ORDER BY COUNT(xnum_kffxp); "PROMPT ___Macro_separator(6)___ "SELECT '| ' || " group_kffxp || '| ' || " number_kffxp || '|' || " name || ' | ' || " COUNT(*) || '|' " FROM x$kffxp, v$asm_alias " WHERE group_kffxp = group_number " AND number_kffxp = file_number " AND system_created = 'Y' " GROUP BY group_kffxp, number_kffxp, name " ORDER BY group_kffxp, number_kffxp; "PROMPT ___Macro_separator(7)___ "SELECT '| ' || " f.group_number || '| ' || " f.file_number || '| ' || " bytes || '| ' || " space || '| ' || " space/1048576 || '|' || " a.name || ' |' " FROM v$asm_file f, v$asm_alias a " WHERE f.group_number = a.group_number " AND f.file_number = a.file_number " AND system_created = 'N' " ORDER BY f.group_number, f.file_number; } } else {var @TTL = ('',\ '---+ File Utilization',\ '---+ File utilization but using the Alias names.',\ '---+ Files stored in Diskgroup') var @HDR = ('',\ '| *Group No*| *File No*| *Bytes*| *Space*| *In MiB*|*Name*|',\ '| *Group No*| *File No*| *Bytes*| *Space*| *In MiB*|*Name*|',\ '| *Group No*| *File No*|*Full Alias Path*|') set $sql {SELECT '| ' || " f.group_number || '| ' || " f.file_number || '| ' || " bytes || '| ' || " space || '| ' || " space/1048576 || '|' || " a.name || ' |' " FROM v$asm_file f,v$asm_alias a " WHERE f.group_number = a.group_number " AND f.file_number = a.file_number " AND system_created = 'Y' " ORDER BY f.group_number,f.file_number; "PROMPT ___Macro_separator(2)___ "SELECT '| ' || " f.group_number || '| ' || " f.file_number || '| ' || " bytes || '| ' || " space || '| ' || " space/1048576 || '|' || " a.name || ' |' " FROM v$asm_file f,v$asm_alias a " WHERE f.group_number = a.group_number " AND f.file_number = a.file_number " AND system_created = 'N' " ORDER BY f.group_number,f.file_number; "PROMPT ___Macro_separator(3)___ "SELECT '| ' || " gnum || '|' || " filnum || ' |' || " concat('+'||gname,sys_connect_by_path(aname, '/')) || '| ' " FROM (SELECT g.name gname, a.parent_index pindex, " a.name aname, a.reference_index rindex, " a.group_number gnum,a.file_number filnum " FROM v$asm_alias a,v$asm_diskgroup g " WHERE a.group_number = g.group_number) " START WITH (mod(pindex, power(2, 24))) = 0 " CONNECT BY PRIOR rindex = pindex; } } call separator(1) call writeSql($sql,2) call separator(0,'File/Space Related Information') =head2 asmexa - Exadata Information Gets Exadata information. =cut debug ' Inside ASM module, gathering Exadata information' report asmexa var $TTL = '---+!! Exadata Information' var @TTL = ('',\ '---+ V$Cell',\ '---+ V$Cell_State',\ '---+ V$Cell_Thread_History',\ '---+ V$Cell_Request_Totals') var $sql = undef var ($HDR[1],$col1) = getSqlColumns('RDA','','V$CELL') call clearSqlColumns('RDA') if $col1 {append $sql {SELECT :1 " FROM v$cell; } } var ($HDR[2],$col2) = getSqlColumns('RDA','','V$CELL_STATE') call clearSqlColumns('RDA') if $col2 {append $sql {PROMPT ___Macro_separator(2)___ "SELECT :2 " FROM v$cell_state; } } var ($HDR[3],$col3) = getSqlColumns('RDA','','V$CELL_THREAD_HISTORY') call clearSqlColumns('RDA') if $col3 {append $sql {PROMPT ___Macro_separator(3)___ "SELECT :3 " FROM (SELECT * " FROM v$cell_thread_history " WHERE snapshot_time > SYSDATE - 1 " ORDER BY snapshot_time DESC) " WHERE ROWNUM < 1000; } } var ($HDR[4],$col4) = getSqlColumns('RDA','','V$CELL_REQUEST_TOTALS') call clearSqlColumns('RDA') if $col4 {append $sql {PROMPT ___Macro_separator(4)___ "SELECT :4 " FROM (SELECT * " FROM v$cell_request_totals " WHERE snapshot_time > SYSDATE - 1 " ORDER BY snapshot_time DESC) " WHERE ROWNUM < 1000; } } if $sql {call separator(1) call writeSql(bindSql($sql,$col1,$col2,$col3,$col4)) call separator(0,'Exadata Information') } } =head2 rpm_info - ASM Library Information On Linux, it gets related package manager information. =cut if match($OSN,'linux') {debug ' Inside ASM module, getting ASM library information' report rpm_info prefix {write '---+!! ASM Library Information' write '---## Using: rpm -qa | grep oracleasm' write '' } loop $lin (grepCommand('rpm -qa','oracleasm')) write $lin if isCreated(true) {write '' toc '2:[[',getFile(),'][rda_report][ASM Library Information]]' } =head2 asmlib_config - ASM Library Configuration On Linux, it collects the F file. =cut debug ' Inside ASM module, collecting /etc/sysconfig/oracleasm file' report asmlib_config var $fil = '/etc/sysconfig/oracleasm' prefix {write '---+!! ASM Library Configuration' write '---## From ',encode($fil) } call writeFile($fil) if isCreated(true) toc '2:[[',getFile(),'][rda_report][ASM Library Configuration]]' =head2 asmlib_disks - ASM Library Disk Information On Linux, it gets ASM library disk information. =cut debug ' Inside ASM module, getting ASM library disk information' report asmlib_disks var $cmd = '/bin/ls -l /dev/oracleasm/disks' prefix {write '---+!! ASM Library Disk Information' write $TOC write '---+ List of Oracle ASM Devices' write '---## Using: ',encode($cmd) } call writeCommand($cmd) if hasOutput(true) write $TOP var $cmd = '/etc/init.d/oracleasm listdisks' if loadCommand($cmd) {prefix {write '---+ List of Oracle ASM Disks' write '---## Using: ',encode($cmd) } call writeLastFile() if hasOutput(true) write $TOP loop $dsk (grepLastFile('.')) {var $cmd = concat('/etc/init.d/oracleasm querydisk ',$dsk) prefix {write '---+ Disk Information for ',$dsk write '---## Using: ',encode($cmd) } call writeCommand($cmd) if hasOutput(true) write $TOP } } if isCreated(true) toc '2:[[',getFile(),'][rda_report][ASM Library Disk Information]]' =head2 partitions - Disk Partitions On Linux, it gets the disk partition information used to identify the physical devices with the ASM disk. =cut debug ' Inside ASM module, getting disk partitions information' report partitions var $fil = '/proc/partitions' prefix {write '---+!! Disk Partition Information' write '---## From ',encode($fil) } call writeFile($fil) if isCreated(true) toc '2:[[',getFile(),'][rda_report][Disk Partitions]]' =head2 udev - Udev Settings On Linux, it gets the udev settings information. =cut debug ' Inside ASM module, getting udev settings information' report udev var $dir = '/etc/udev/rules.d' pretoc '2:Udev Settings' prefix {write '---+!! Udev Settings Information' write '---## From ',encode($dir) } call sort_files(3,0,grepDir($dir,'.','p')) unpretoc } =head2 dev_list - Device List Lists the devices from the F directory. =cut debug ' Inside ASM module, getting device information' report dev_list macro stat_dev {var ($dir) = @arg import $TOP call statDir('an',$dir) write $TOP loop $fil (grepDir($dir,'^\.+$','nv')) {var $pth = catFile($dir,$fil) if testFile('dr',$pth) {next testFile('l',$pth) call stat_dev($pth) } } } var $dir = '/dev' prefix write '---+!! Listing of Devices from ',encode($dir) if testFile('dr',$dir) call stat_dev($dir) if isCreated(true) toc '2:[[',getFile(),'][rda_report][Device List]]' =head2 dev_header - ASM Devices Header Information Collects the ASM devices header information. =cut var ($pat0,$pat1,%dev,%fil) = (\ '^(\.+|agp|arp|audio|audit|bd\.off|bus|cd|ce|clone|conslog|console|control|\ core|cua|diskette|dmp|dri|dsp|dssa|dump|dvd|echo|ecp|envctrl|eri|error|\ event|fb|fd|full|ge|gxme|hdlc|hme|hpet|icmp|infiniband|input|ip|ipldevice|\ isa|iscsi|kb|key|kstat|ksyms|le|lft|llc|lofictl|log|loop|lp|MAKEDEV|md|mem|\ mice|mixer|mouse|nca|net|nrst|nul|openprom|paging|par0|pci|pm|poll|port|\ ppp|print|ptc|ptmajor|ptmx|pts|pty|qe|qfe|ram|random|rawctl|rawip|rcd|rcm|\ refresh|rmt|root|rtc|rts|sad|sctp|sequencer|sg|slog|snap|snd|spx|ssa|\ stderr|stdin|stdout|swap|SWAP|syscon|systrace|systrctl|tcp|term|tic.?ts|\ tnf|tod|tty|udp|unixdg|unixst|usb|vbi|vcs|video|volctl|vx|winlock|wrsmd|\ wscons|X0R|zero)',\ '^(\.+|agp|arp|audio|audit|bd\.off|bus|cd|clone|conslog|console|control|core|\ cua|diskette|dmp|dri|dsp|dssa|dump|dvd|echo|ecp|envctrl|error|event|fd|\ full|gxme|hdlc|hpet|icmp|infiniband|input|ipldevice|isa|iscsi|key|kstat|\ ksyms|lft|llc|lofictl|loop|MAKEDEV|md|mem|mice|mixer|mouse|net|nrst|\ openprom|paging|par0|poll|port|ppp|print|ptmajor|ptmx|pts|ram|random|\ rawctl|rawip|refresh|root|rtc|sctp|sequencer|sg|snap|snd|stderr|stdin|\ stdout|swap|SWAP|syscon|systrace|systrctl|tcp|term|tic.?ts|tnf|tty|udp|\ unixdg|unixst|usb|vbi|vcs|video|volctl|winlock|wrsmd|wscons|X0R|zero)') # Get the devices macro get_devices {var (\%dev,$dir,$pat,$nxt) = @arg # Analyze the directory loop $fil (grepDir($dir,$pat,'nv')) {var $pth = catFile($dir,$fil) if testDir('d',$pth) var $sub{$pth} = true else var $dev{$pth} = true } # Treat the sub directories loop $sub (keys(%sub)) call get_devices(\%dev,$sub,$nxt,$nxt) } call get_devices(\%dev,$dir,$pat0,$pat1) # Collect ASM header properties if testFile('x',catFile($ORACLE_HOME,'bin','kfed')) {debug ' Inside ASM module, getting devices header information' report dev_header prefix write '---+ Display of ASM Devices Header Information' loop $fil (keys(%dev)) {if loadCommand(concat(lastCommand(),' read ',$fil,' 2>&1'),true,1) {next !grepLastFile('kfbh\.type','f') next match(last,'KFBTYP_INVALID|Unknown\s*Enum') next $fil{$fil} if grepLastFile('ausize|blksize|driver\.provstr|dskname|dsknum|dsksize|\ fgname|grpname|grptyp|hdrsts') {var @dev = last var $fil{$fil} = replace(join("\001",@dev),'\s+','',true) write '| *',encode($fil),'* |' loop $lin (@dev) write '|',$lin,' |' } } } if hasOutput(true) {write $TOP toc '2:[[',getFile(),'][rda_report][ASM Devices Header Information]]' } =head2 dev_duplicates - Potential Duplicate Devices Collects the potential duplicate devices information. =cut # Collect ASMLIB devices information debug ' Inside ASM module, getting duplicate devices information' report dev_duplicates prefix write '---+ Display of Potential Duplicate Devices' var @fil = keys(%fil) var $cnt = @fil decr $cnt for $off1 (0,$cnt,1) {var $lin1 = $fil{$fil[$off1]} for $off2 ($off1,$cnt,1) {next expr('==',$off1,$off2) var $lin2 = $fil{$fil[$off2]} if compare('eq',$lin1,$lin2) {if match($fil[$off1],'oracleasm',true) write '|``',encode($fil[$off1]),' is the ASMLIB device corresponding to ',\ encode($fil[$off2]),'``|' elsif match($fil[$off2],'oracleasm',true) write '|``',encode($fil[$off2]),' is the ASMLIB device corresponding to ',\ encode($fil[$off1]),'``|' else write '|``',encode($fil[$off1]),' is a duplicate of ',encode($fil[$off2]),\ '``|' } } } if hasOutput(true) {write $TOP toc '2:[[',getFile(),'][rda_report][Potential Duplicate Devices]]' } } # Get the dump destinations call find_dest('ASM_') var $BDUMP_DIR = get_bdump() var $CDUMP_DIR = get_cdump() var $UDUMP_DIR = get_udump() var $ADR_BASE = get_adr_base() var $ADR_HOME = get_adr_home() var $ALERT_TAIL = getSetting('ASM_ALERT_TAIL',30000) var $TRACE_DIR = cond($ADR_HOME,catDir($ADR_HOME,'trace'),$BDUMP_DIR) # Define a macro to estimate the size after compression macro get_size {var ($fil) = @arg import $LOG_RATIO,$LOG_TRESHOLD keep $LOG_RATIO,$LOG_TRESHOLD var $siz = getSize($fil) if expr('>',$siz,$LOG_TRESHOLD) var $siz = expr('/',$siz,$LOG_RATIO) return $siz } =head2 alert_log - Alert Log Gathers the alert Log Information. =cut var @err = () if and($ADR_HOME,not($ALERT_TEXT)) {debug ' Inside ASM module, found diagdir ',$ADR_HOME,', get log info' var $fil = catFile($ADR_HOME,'alert','log.xml') if createBuffer('ALR','R',$fil) {# Parse the alert log for errors and last startup macro push_err {var (\@err,$lin,$max) = @arg if expr('<',scalar(@err),$max) var @err = (@err,$lin) else var (undef,@err) = (@err,$lin) return -1 } var $lst = undef call parseReset() call parseVar($lin) call parsePattern('TOP',\ '^',$lst,$min) var $lst = undef } if $lst {var $cnt = expr('-',$max,$lst) incr $cnt call setPos('ALR',$pos) } else {call setPos('ALR') while getLine('ALR',$min) {var $lin = chomp(last) break match($lin,'^',quote($out,'x'),' 2>',quote($err,'x'))) pretoc '2:Diagnostic Repository' report diag_problems if testFile('z',$out) {echo 'Error encountered with ADRCI' write '** Error encountered with ADRCI **' write call writeFile($err) } elsif createBuffer('ADR','R',$out) {var ($cnt,$min,$cut,$src,$hdr) = (0,0,true) prefix {write '---+ List of Diagnostic Problems' write '---## Using: SHOW PROBLEM -ALL -ORDERBY LASTINC_TIME DSC' if $src write '---## From: ',replace(encode($src),'\s',' ',true) if $hdr write $hdr } while getLine('ADR') {var $lin = chomp(last) if match($lin,'^ADR Home\s+=\s*(.*):$') var ($cut,$row,$src) = (false,false,last) elsif match($lin,'^DIA\-(\d+):') {if $src write '**',$lin,'**' break } elsif $cut next elsif match($lin,'^\d+\s+rows\s+fetched$') {if !isCreated() {var $hdr = undef write '**No problems found**' } break } elsif $row {next expr('<',length($lin),$min) var @tbl = () for $pos (0,$cnt) var $tbl[$pos] = trim(substr($lin,$tb_off[$pos],$tb_lgt[$pos])) if @tbl write '|',join(' |',@tbl),' |' } elsif match($lin,'^[\-\s]+$') var $row = true elsif match($lin,'^\w+\s+') {var ($min,@tb_key,@tb_lgt,@tb_off) = (0) var %tbl = ('PROBLEM_ID','Problem ID',\ 'PROBLEM_KEY','Problem Key',\ 'LAST_INCIDENT','Last Incident',\ 'LASTINC_TIME','Last Incident Time') var $lin = trim($lin) while match($lin,'^(\w+\s+)') {var ($key) = last var $lgt = length($key) var $key = trim($key) var $tb_key[$cnt] = nvl($tbl{$key},$key) var $tb_off[$cnt] = $min var $tb_lgt[$cnt] = $lgt var $lin = substr($lin,$lgt) incr $min,$lgt incr $cnt } var $tb_key[$cnt] = nvl($tbl{$lin},$lin) var $tb_off[$cnt] = $min if $cnt var $hdr = concat('|*',join('*|*',@tb_key),'*|') } } call deleteBuffer('ADR') } call unlinkTemp('job') call unlinkTemp('out') call unlinkTemp('err') if isCreated(true) toc '3:[[',getFile(),'][rda_report][Problem Overview]]' =head3 diag_incidents - Most Recent Incidents Gathers diagnostic incidents. An incident is a single occurrence of a problem. When a problem (critical error) occurs multiple times, an incident is created for each occurrence. Incidents are time stamped and tracked in the Automatic Diagnostic Repository. By default, RDA will collect the last 10 incidents. It requires the availability of the ADRCI utility. =cut var $MAX = getSetting('ASM_INCIDENTS',10) var $max = $MAX if $max {var ($cut,@inc,%lnk) = (true) # Get the incident list var $job = createTemp('job') var $out = getTemp('out') call writeTemp('job','SET BASE ',$ADR_BASE) call writeTemp('job','SET HOMEPATH ',$hom) call writeTemp('job','QUERY (INCIDENT_ID) INCIDENT -ORDERBY CREATE_TIME DSC') call writeTemp('job','EXIT') call closeTemp('job') call command(concat($cmd,' script=',quote($job,'x'),' >',quote($out,'x'))) if createBuffer('ADR','R',$out) {while getLine('ADR') {var $lin = chomp(last) if match($lin,'^-+\s*$') var $cut = false elsif $cut next elsif match($lin,'^(\d+)\s*$') var @inc = (@inc,last) elsif match($lin,'^\d+\s+rows\s+fetched$') break } call deleteBuffer('ADR') } # Get the incident details loop $inc (@inc) {var $job = createTemp('job') var $out = getTemp('out') call writeTemp('job','SET BASE ',$ADR_BASE) call writeTemp('job','SET HOMEPATH ',$hom) call writeTemp('job','SHOW INCIDENT -MODE DETAIL -P "INCIDENT_ID=',$inc,'"') call writeTemp('job','EXIT') call closeTemp('job') call command(concat($cmd,' script=',quote($job,'x'),' >',quote($out,'x'))) if createBuffer('ADR','R',$out) {report concat('incident_',$inc) var ($cut,$src) = (true) prefix {write '---+ Display of Incident ',$inc write '---## Using: SHOW INCIDENT -MODE DETAIL -P "INCIDENT_ID=',$inc,'"' if $src write '---## From: ',replace(encode($src),'\s',' ',true) write '|*Name*|*Value*|' } while getLine('ADR') {var $lin = chomp(last) if match($lin,'^ADR Home\s+=\s*(.*):$') var ($cut,$src) = (false,last) elsif $cut next elsif match($lin,'^\s+\w+\s') {var (undef,$nam,$val) = split('\s+',$lin,3) write '|',$nam,' |',$val,' |' } elsif match($lin,'^\d+\s+rows\s+fetched$') break } if isCreated(true) {write $TOP var $lnk{$inc} = getFile() } call deleteBuffer('ADR') } call unlinkTemp('job') call unlinkTemp('out') # Limit the incident number decr $max break !$max } report diag_incidents prefix {write '---+ Display of Last ',$MAX,' Incidents' write '| *Incident ID*|' } loop $inc (@inc) {if exists($lnk{$inc}) write '| [[',$lnk{$inc},'][_blank][',$inc,']]|' } if isCreated(true) toc '3:[[',getFile(),'][rda_report][Most Recent Incidents]]' } unpretoc } =head2 log_trace - Trace/Log Directory Listings Lists the contents of the trace/dump directories. =cut debug ' Inside ASM module, doing list of Oracle trace/log directories' report log_trace write '---+!!Listing of Files from Oracle Log/Trace Directories' write $TOC if $ADR_HOME {write '---+ Diagnostic Traces' if !statDir('at',catDir($ADR_HOME,'trace')) write 'Could not list files in ',encode(lastDir()),'%BR%' write $TOP write '---+ Incidents' if !statDir('at',catDir($ADR_HOME,'incident')) write 'Could not list files in ',encode(lastDir()),'%BR%' write $TOP write '---+ Incident Packages' if !statDir('at',catDir($ADR_HOME,'incpkg')) write 'Could not list files in ',encode(lastDir()),'%BR%' write $TOP write '---+ Core Dumps' if !statDir('at',catDir($ADR_HOME,'cdump')) write 'Could not list files in ',encode(lastDir()),'%BR%' write $TOP if match(getOsName(),'solaris') {run COREinfo() call run_coreadm((concat('_',$ORACLE_SID,'\b'))) } } write '---+ Background Dump Destination' if !$BDUMP_DIR write 'Background Dump destination could not be determined.%BR%' elsif !statDir('at',$BDUMP_DIR) write 'Could not list files in ',encode($BDUMP_DIR),'%BR%' write $TOP var $dir = catDir($ORACLE_HOME,'rdbms','log') if compare('ne',$BDUMP_DIR,$dir) {write '---+ Default Background Dump Destination.%BR%' if !statDir('at',$dir) write 'Could not list files in ',encode($dir),'%BR%' write $TOP } write '---+ Core Dump Destination' if !$CDUMP_DIR write 'Core Dump destination could not be determined.%BR%' elsif !statDir('at',$CDUMP_DIR) write 'Could not list files in ',encode($CDUMP_DIR),'%BR%' write $TOP var $dir = catDir($ORACLE_HOME,'dbs') if compare('ne',$CDUMP_DIR,$dir) {write '---+ Default Core Dump Destination' if !statDir('at',$dir) write 'Could not list files in ',encode($dir),'%BR%' write $TOP if match(getOsName(),'solaris') {run COREinfo() call run_coreadm((concat('_',$ORACLE_SID,'\b'))) } } write '---+ User Dump Destination' if !$UDUMP_DIR write 'User Dump destination could not be determined.%BR%' elsif compare('eq',$UDUMP_DIR,$BDUMP_DIR) write 'User Dump destination and Background Dump destination are the same.\ %BR%Please see Background Dump destination for listing.%BR%' elsif !statDir('at',$UDUMP_DIR) write 'Could not list files in ',encode($UDUMP_DIR),'%BR%' write $TOP var $dir = catDir($ORACLE_HOME,'rdbms','trace') write '---+ RDBMS Trace Destination' if !statDir('at',$dir) write 'Could not list files in ',encode($dir),'%BR%' write $TOP toc '2:[[',getFile(),'][rda_report][Trace/Log Directory Listings]]' =head2 Most recent trace files Collects the most recent trace files for each type of background process. Older files are not considered. When requested, RDA can collect the most recent user dumps. =cut var @tbl = () if and($UDUMP_DIR,$UDUMP_AGE) var @tbl = grepDir($UDUMP_DIR,concat('^',quote($ORACLE_SID),'_.*\.trc$'),\ concat('iptm',$UDUMP_AGE)) if and($TRACE_DIR,$BDUMP_MAX) {var %ref = () loop $fil (grepDir($TRACE_DIR,\ concat('^',quote($ORACLE_SID),'_[^_\.]+_.*\.trc$'),'it')) {var $typ = field('_',1,$fil) var $fil = catFile($TRACE_DIR,$fil) next !isNewer($fil,$LOG_AGE) incr $ref{$typ} next expr('>',$ref{$typ},$BDUMP_MAX) var @tbl = (@tbl,$fil) } } call sort_files(3,0,@tbl) # Restore the previous context call setSqlSid($sid) call setSqlLogin($old) call setSqlFailure($try) if $DISTINCT_HOME call setEnv('ORACLE_HOME',$env) =head1 SEE ALSO L, L, L =begin credits =over 10 =item RDA 4.2: Michael Ferrante, Noriyuki Kamei, Roger Snowden. =item RDA 4.4: Bane Radulovic, Guttula Srinivas. =item RDA 4.5: Bob Caldwell, Jaime Figueroa, Guttula Srinivas, Jens Voigt. =item RDA 4.7: Weifeng Xie. =item RDA 4.13: Jean-Marc Gaudron. =item RDA 4.14: Jean-Marc Gaudron. =item RDA 4.15: Jean-Marc Gaudron. =item RDA 4.16: Jean-Marc Gaudron. =item RDA 4.17: Jean-Marc Gaudron, Scott Jesse. =back =end credits =head1 COPYRIGHT NOTICE Copyright (c) 2002-2009, Oracle. All rights reserved. =head1 TRADEMARK NOTICE Oracle, JD Edwards, PeopleSoft, and Siebel are registered trademarks of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. =cut