# MCilmb.ctl:203: Collects Integrated Lights Out Manager (ILOM) Information # $Id: MCilmb.ctl,v 1.14 2015/05/09 15:08:05 RDA Exp $ # ARCS: $Header: /home/cvs/cvs/RDA_8/src/scripting/lib/collect/EXPLORER/MCilmb.ctl,v 1.14 2015/05/09 15:08:05 RDA Exp $ # # Change History # 20150509 MSC Change handle management. =head1 NAME EXPLORER:MCilmb - Collects Integrated Lights Out Manager (ILOM) Snapshot Information =head1 DESCRIPTION This module collects Integrated Lights Out Manager (ILOM) snapshot information. The following reports can be generated and are regrouped under C: =cut use Buffer use Mrc use Remote # Initialization var $VALIDATE = true keep $VALIDATE section begin var $ERR = '---## Associated Errors' var $GRP = 'explorer:ilomsnp' var $TOC = '%TOC%' var $TOP = '[[#Top][Back to top]]' run EXPLORER:XPLRlib('ilomsnapshot_start') # Get commands syntax var $GETENT = '/usr/bin/getent hosts "%s" 2>/dev/null' var $PING = check(${RDA.T_OS},\ 'solaris',concat(${CMD.PING:'ping'},' %s'),\ 'linux', concat(${CMD.PING:'ping'},' -c 1 %s'),\ 'cygwin', concat(${CMD.PING:'ping'},' %s 64 1')) var $SU = concat(${CMD.SU:'su'},' - "%s"') #------------------------------------------------------------------------------ # XPLR_ilomsnp_start section #------------------------------------------------------------------------------ section XPLR_ilomsnp_start # Validate the execution context if !${B_GLOBAL:true} return call log_run('Processing ILMB sections ...') pretoc '2:Integrated Lights Out Manager (ILOM) Snapshot Start' # Define a macro to parse .explorer file macro parse_explorer {var ($buf,$dat) = @arg var ($hst,$usr) = split('\|',$dat,2) import %ARC keep %ARC var $sct = undef loop $lin ($buf->grep('^\s*($|#)','v')) {if match($lin,'^\s*\[') var ($sct) = match($lin,'^\s*\[ILOM:(\w[\w\-\.]*)\]') elsif ?$sct {if match($lin,'^\s*(CLN|DIR|ENC|HST|KEY|SCH|TYP|USR)\s*=\s*"(.*)"',true) {var ($key,$val) = last var $ARC{$hst,$usr,$sct,lc($key)} = $val } } } } =head2 Integrated Lights Out Manager (ILOM) Snapshot Information Connects through F or SSH to the specified user on the archive host to retrieve snapshot archival context from the F<${HOME}/.explorer> file. You should create that file in order to collect a snapshot. File F<${HOME}/.explorer> should be owned by the archival user and its permissions should be 400 or 600. Since other ILOM or SP units can use the same archival user, each of them has a specific section in the F<${HOME}/.explorer> file. A typical ILOM section looks like this: [ILOM:i3000_102] CLN="FILE" DIR="ilomsnap" ENC="FALSE" HST="xxx.xxx.xxx.xxx" KEY="i_102" SCH="sftp" TYP="fruid" USR="expltest" For a ILOM section, we have: =over 2 =item o A section header C<[ILOM:name_of_section]> regroups a set of keywords and their values to describe a specific archival context. The section name must start with a word, which is composed of letters, digits, and underscores, possibly followed by letters, digits, underscores, dashes, and periods. =item o =for stopwords hostname C specifies the ILOM host. When a hostname[.domain] is used, the ILOM must be able to resolve it. An IP address is an alternative. =item o C specifies the ILOM user, used to take the snapshot. =item o C specifies the encryption mode. It supports the following modes: =over 2 =item o C: Output encryption enabled =item o C: Output encryption disabled (default) =back =item o =for stopwords dataset C specifies the snapshot dataset type. It supports the following ones: =over 2 =item o C: Collects ILOM, SPOS, and Hardware information. =item o C: Collects only "log" files for the normal dataset. =item o C: Collects collects everything in "normal" dataset plus FRUID information. (default) =item o C: =for stopwords fruid Collects only "log" files for the fruid dataset. =back =item o C indicates the snapshot directory. A relative path is taken from the user home directory. Its full path cannot contain single or double quotation marks. The snapshot directory should be owned by the archival user and its permissions should be 700. =item o C specifies the cleanup strategy. It supports the following strategies: =over 2 =item o C: Removes all files from destination directory. =item o C: Removes the snapshot file collected by Oracle Explorer. (default) =item o C: Disables any cleanup. =item o C: Removes all files from the destination directory, with a name matching the indicated pattern. For example, CLN="PAT:*.zip" =back =item o C specifies an optional identification key, which can be used to indicate that multiple entries are using the same password. =item o C specifies the snapshot file transfer scheme. It supports the following schemes: =over 2 =item o C: File Transfer Protocol (FTP) =item o C: Secure File Transfer Protocol (SFTP) (default) =back =back Once it has retrieved the snapshot context, this module gathers the following Integrated Lights Out Manager (ILOM) commands through SSH (requires a working Java environment): =over 2 =item o C =item o C =item o C =item o C =back ${DATASET} represents the set of information to be collected. ${DIR} represents the location where the snapshot file will be placed in the archive host. ${ENCRYPT} represents the snapshot file encryption mode. ${HOST} represents the archive host. ${SCH} represents the scheme to be used for transferring the snapshot file to the archive host. ${USER} represents the user to connect to the archive host. =cut var (%ARC,%DSC,%DUP) = () # Treat all requests loop $set (@{MOD.ILMB.N_SET}) {var $nod = ${MOD.ILMB.T_HOST_${VAR.set}} next !?$nod # Validate the input parameters var ($a_f,$a_s,$snp) = (false) var $sct = ${MOD.ILMB.T_SECTION_${VAR.set}} if !match($sct,'^\w[\w\-\.]*$') next log_info(concat('Bad section name "',$sct,'".')) var $val = ${MOD.ILMB.T_USER_${VAR.set}} if !?$usr = isUser($val,true) next log_info(concat('Bad archive user name "',$val,'".')) if compare('eq',$nod,'-') var $hst = ${RDA.T_HOST} else {debug ' Inside ILMB collection, validating ',$nod,' access' if !?$hst = isHost($nod,true) next log_info(concat('Bad archive host name or IP "',$nod,'".')) call command(sprintf($PING,$hst)) if status() next log_info(concat('Host ',$hst,' is not reachable.')) var $a_s = addRemoteSession('ARC',$hst,$usr) if and($a_s->set_type('da'),$a_s->set_type('jsch')) {if $a_s->set_type('ssh') next log_info(concat('Cannot create a session to host ',$hst)) var $a_f = true } # Make sure SSH agent is running if !$a_s->has_agent call $a_s->set_agent # Ask for the password when necessary if and($a_s->need_password,\ not(hasPassword('host',$hst,$usr))) call setPassword('host',$hst,$usr,askPassword(concat('Enter ',$usr,\ ' password for Archive host ',$hst,': '),'')) } # Obtain archive host IP address needed for snapshot command if !?$adr = isIP($hst,true) {if !?$adr = isIP(field('\s',0,command(sprintf($GETENT,$hst))),true) next log_info(concat('Unable to get IP address for "',$hst,'"')) } # Create temporary file to be used to store outputs debug ' Inside ILMB collection, obtaining information from ',$hst var $res = getTemp(concat('TMP',$hst)) # Obtain archive host information when necessary if missing($ARC{$hst,$usr,$sct}) {set $cod {if [ -x '/bin/uname' ] "then " OSN=`/bin/uname -s` "elif [ -x '/usr/bin/uname' ] "then " OSN=`/usr/bin/uname -s` "else " OSN='other' "fi "case "${OSN}" in " CYGWIN*) CMD_CAT='/bin/cat' " CMD_EGREP='/bin/egrep' " CMD_FIND='/bin/find' " CMD_LS='/bin/ls' " CMD_MKDIR='/bin/mkdir' " CMD_RM='/bin/rm' " ;; " Linux*) CMD_CAT='/bin/cat' " CMD_EGREP='/bin/egrep' " CMD_FIND='/usr/bin/find' " CMD_LS='/bin/ls' " CMD_MKDIR='/bin/mkdir' " CMD_RM='/bin/rm' " ;; " SunOS*) CMD_CAT='/usr/bin/cat' " CMD_EGREP='/usr/bin/egrep' " CMD_FIND='/usr/bin/find' " CMD_LS='/usr/bin/ls' " CMD_MKDIR='/usr/bin/mkdir' " CMD_RM='/usr/bin/rm' " ;; " *) CMD_CAT='/bin/cat' " CMD_EGREP='/bin/egrep' " CMD_FIND='/usr/bin/find' " CMD_LS='/bin/ls' " CMD_MKDIR='/bin/mkdir' " CMD_RM='/bin/rm' " ;; "esac " "echo "---# RDA:SET VARIABLE:ILMB:HOME=\"${HOME}\"" "echo "---# RDA:SET VARIABLE:ILMB:CMD_CAT=\"${CMD_CAT}\"" "echo "---# RDA:SET VARIABLE:ILMB:CMD_EGREP=\"${CMD_EGREP}\"" "echo "---# RDA:SET VARIABLE:ILMB:CMD_FIND=\"${CMD_FIND}\"" "echo "---# RDA:SET VARIABLE:ILMB:CMD_LS=\"${CMD_LS}\"" "echo "---# RDA:SET VARIABLE:ILMB:CMD_MKDIR=\"${CMD_MKDIR}\"" "echo "---# RDA:SET VARIABLE:ILMB:CMD_RM=\"${CMD_RM}\"" " "FIL="${HOME}/.explorer" "if [ ! -f "${FIL}" ] "then " echo '---# RDA:BEGIN CAPTURE:TEST' " echo 'NO_EXPLORER' " echo '---# RDA:END CAPTURE' "elif ! [ -O "${FIL}" ] "then " echo '---# RDA:BEGIN CAPTURE:TEST' " echo 'OWNER_ERROR' " echo '---# RDA:END CAPTURE' "elif "${CMD_LS}" -ldn "${FIL}" 2>/dev/null | \ "${CMD_EGREP}" '^-r[-w]-------' >/dev/null 2>&1 "then " echo '---# RDA:BEGIN CAPTURE:TEST' " echo 'CORRECT' " echo '---# RDA:END CAPTURE' " echo '---# RDA:BEGIN' " "${CMD_CAT}" "${FIL}" " echo '---# RDA:END MACRO parse_explorer::1|:2' "else " echo '---# RDA:BEGIN CAPTURE:TEST' " echo 'PERMISSIONS_ERROR' " echo '---# RDA:END CAPTURE' "fi } var $cod = bind($cod,$hst,$usr) # Provide step information as password may be requested by SSH if $a_f call log_critical(concat('Obtaining information from ',$hst)) # Run the code if ?$a_s call rcollect('ARC',$cod,$res) else {output | concat(sprintf($SU,$usr),'>',quote($res)) write $cod close } # Analyze the results call writeRemoteResult($res,'ARC') var $DSC{$hst,$usr} = {getRemoteGroup('ILMB')} # Verify home directory for the archive user was found if missing($DSC{$hst,$usr,'HOME'}) next log_info($ARC{$hst,$usr,$sct} = \ concat('Unable to find home directory for archive user ',$usr)) # Verify that .explorer file exists var $buf = getRemoteBuffer('TEST',true) if !$buf->grep('^CORRECT$') {var $fil = catFile($DSC{$hst,$usr,'HOME'},'.explorer') if $buf->grep('^OWNER_ERROR') next log_info(concat('The ',$fil,' file is not owned by user ',$usr)) if $buf->grep('^PERMISSIONS_ERROR') next log_info(concat('Access to the ',$fil,\ ' file is not restricted to its owner')) next log_info(concat('Unable to find a valid ',$fil,' file at archive host')) } call $buf->close # Verify .explorer file was successfully parsed if !?$rec = $ARC{$hst,$usr,$sct} next log_info($ARC{$hst,$usr,$sct} = \ concat('Unable to obtain information from ',\ catFile($DSC{$hst,$usr,'HOME'},'.explorer'))) } elsif !ref($rec = $ARC{$hst,$usr,$sct}) next log_info($rec) # Obtain section information for later use var $dsc = $DSC{$hst,$usr} var ($cln,$dir,$enc,$key,$sch,$typ,$v_h,$v_u) = ($rec->{'cln'},\ $rec->{'dir'},\ $rec->{'enc'},\ $rec->{'key'},\ $rec->{'sch'},\ $rec->{'typ'},\ $rec->{'hst'},\ $rec->{'usr'}) var $hom = $DSC{$hst,$usr,'HOME'} # Reject a duplicate request if ?$DUP{$v_h} next log_info(concat('Already tried snapshot collection from ILOM ',$v_h)) var $DUP{$v_h} = true # Ensure archive directory fullfils the requirements debug ' Inside ILMB collection, validating required setup at ',$hst if !isAbsolute($dir = nvl($rec->{'dir'},catDir($hom,'ilom_snapshot'))) var $dir = catDir($hom,$dir) if match($dir,'[\042\047]') next log_info(concat('The ',$dir,\ ' directory contains unsupported characters')) set $cod {if ! [ -e ':1' ] "then " "${CMD_MKDIR}" -m 700 -p ':1' && echo 'CREATED' "elif ! [ -O ':1' ] "then " echo 'OWNER_ERROR' "elif "${CMD_LS}" -ldn ':1' 2>/dev/null | \ "${CMD_EGREP}" '^drwx------' >/dev/null 2>&1 "then " echo 'CORRECT' "else " echo 'DIRECTORY_ERROR' "fi } var $cod = bind($cod,$dir) # Provide step information as password may be requested by SSH if $a_f call log_critical(concat('Validating required setup at ',$hst)) # Run the code if ?$a_s call rcollect('ARC',$cod,$res,{CMD_EGREP => $dsc->{'CMD_EGREP'},\ CMD_LS => $dsc->{'CMD_LS'},\ CMD_MKDIR => $dsc->{'CMD_MKDIR'}}) else {output | concat(sprintf($SU,$usr),'>',quote($res)) write 'CMD_EGREP="',$dsc->{'CMD_EGREP'},'"' write 'CMD_LS="', $dsc->{'CMD_LS'},'"' write 'CMD_MKDIR="',$dsc->{'CMD_MKDIR'},'"' write $cod close } # Verify required archive directory exists and has the correct permissions if !grepFile($res,'^(CORRECT|CREATED)$') {if grepFile($res,'^OWNER_ERROR') next log_info(concat('Archive directory ',$dir,\ ' is not owned by user ',$usr)) elsif grepFile($res,'^DIRECTORY_ERROR') next log_info(concat($dir,' is not a valid or access-restricted archive \ directory')) next log_info(concat('Missing directory ',$dir)) } # Connect to the service controller if !?$v_h next log_info('Missing ILOM host name') if !?$v_u next log_info('Missing ILOM user name') if !?$i_h = isHost($v_h,true) next log_info(concat('Bad ILOM host name or IP "',$v_h,'".')) if !?$i_u = isUser($v_u,true) next log_info(concat('Bad ILOM user name "',$v_u,'".')) debug ' Inside ILMB collection, validating ',$i_h,' access' call command(sprintf($PING,$i_h)) if status() next log_info(concat('Host ',$i_h,' is not reachable.')) debug ' Inside ILMB collection, gathering ',$i_h,' information (can take time)' call log_critical(concat('Starting snapshot on ',$i_h)) var $i_s = addRemoteSession('ILMB',$i_h,$i_u) if and($i_s->set_type('da'),$i_s->set_type('jsch')) next log_error(concat('Unable to run snapshot at ',$i_h)) # Request password when needed if $i_s->need_password {# Share key password if ?$key call samePassword($key,'host',$GRP,[$i_h,$i_u]) # Request missing password if !hasPassword('host',$i_h,$i_u) call setPassword('host',$i_h,$i_u,\ askPassword(concat('Enter ',$i_u,' password for ILOM ',$i_h,': '),'')) } # Login to the service controller if !$i_s->open next log_warning($i_s->get_message) if !?$i_s->login($i_u,{dis=>'exit',\ pat=>'m/>[\x20]?$/'}) next log_warning($i_s->get_message) var $buf = new('Buffer','L') call $buf->set_handle('eol',false) # Verify snapshot is not already running for another session call $i_s->collect($buf,{\ cln => true,\ cmd => 'show /X/diag/snapshot result',\ pat => 'm/->[\x20]?$/',\ skp => true}) if $buf->grep('^\s*result\s+=\s+Running','f') next log_error(concat('Snapshot is already running for another session at ',\ $i_h)) else call $buf->truncate # Select the dataset to collect if !match($typ,'^(fruid|normal)(-logonly)?$') var $typ = 'fruid' var $cmd = concat('set /X/diag/snapshot dataset=',$typ) call $buf->write(concat('-> ',$cmd)) call $i_s->collect($buf,{\ cln => true,\ cmd => $cmd,\ pat => 'm/->[\x20]?$/',\ skp => true}) # Enable/disable output encryption var $enc = match($enc,'^(y(es)?|on|true)$',true) var $cmd = concat('set /X/diag/snapshot encrypt_output=',\ cond($enc,'TRUE','FALSE')) call $buf->write(concat('-> ',$cmd)) call $i_s->collect($buf,{\ cln => true,\ cmd => $cmd,\ pat => 'm/->[\x20]?$/',\ skp => true}) # Run snapshot command var $dir = replace($dir,'\s','%20',true) if !match($sch,'^ftp$') var $sch = 'sftp' var $cmd = concat('set /X/diag/snapshot dump_uri=',\ quote(concat($sch,'://',$usr,'@',$adr,\ cond(compare('eq',$sch,'ftp'),'/',''),$dir))) var @nwp = ('m/enter\s.*password:\s*$/i',\ ["%s\012",'host',$hst,$usr,\ concat('Enter ',$usr,' password for archive host ',$hst,': '),'']) if $enc {var $phr = askPassword('Enter encryption passphrase for snapshot output \ file: ') call push(@nwp,\ 'm/enter encryption passphrase for snapshot output file:\s*$/i',\ concat($phr,"\012"),\ 'm/confirm encryption passphrase for snapshot output file:\s*$/i',\ concat($phr,"\012")) } call $buf->write(concat('-> ',$cmd)) call $i_s->collect($buf,{\ cln => true,\ cmd => $cmd,\ nwp => [@nwp],\ pat => 'm/->[\x20]?$/',\ skp => true}) # Check snapshot execution status var ($cmd,$max,$try) = ('show /X/diag/snapshot result',$buf->count,3) while expr('>',$try,0) {# Check snapshot execution status call $buf->write(concat('-> ',$cmd)) call $i_s->collect($buf,{\ cln => true,\ cmd => $cmd,\ pat => 'm/->[\x20]?$/',\ skp=>true}) var ($min,$max) = ($max,$buf->count) var @buf = $buf->get_range($min,$max) break grep(@buf,'^\s*result\s+=\s+Running','f') decr $try } # Define settings to be used for collecting the snapshot file if expr('>',$try,0) {call log_critical(concat('Data gathering started for ',$i_h)) var ${RUN.EXPLORER.XPLR.ILME.T_CAT_${VAR.set}} = $dsc->{'CMD_CAT'} var ${RUN.EXPLORER.XPLR.ILME.T_CLN_${VAR.set}} = $cln var ${RUN.EXPLORER.XPLR.ILME.T_DIR_${VAR.set}} = $dir var ${RUN.EXPLORER.XPLR.ILME.T_FIND_${VAR.set}} = $dsc->{'CMD_FIND'} var ${RUN.EXPLORER.XPLR.ILME.T_HOST_${VAR.set}} = $i_h var ${RUN.EXPLORER.XPLR.ILME.T_RM_${VAR.set}} = $dsc->{'CMD_RM'} var ${RUN.EXPLORER.XPLR.ILME.T_USER_${VAR.set}} = $i_u } # Close the connection call $i_s->close # Genererate the collected command report report concat('ilomsnp_b_',$i_h) title '---+!! Integrated Lights Out Manager (ILOM) Snapshot' title '---## ',$i_h,' Snapshot Execution' title $TOC call do_exec(\ {cmd => 'BUFFER',\ buf => $buf,\ det => $cmd,\ nam => join('/','ilom',$i_h,'ilomsnapshot_start.out'),\ ttl => '---++ Snapshot Execution Output'}) if isCreated(true) toc '3:[[',getFile(),'][rda_report][',$i_h,' Snapshot Execution]]' # Free the resources if ?$a_s call $a_s->close call $buf->close call unlinkTemp($res) } # Adjust the table of content unpretoc #------------------------------------------------------------------------------ # Input file conversion section #------------------------------------------------------------------------------ section input # Define the input file parser macro macro parse_input {var ($fil,$flg) = @arg import $GRP keep $GRP var @sta = getStat($fil) if !expr('&',$sta[2],077) {# Parse the input file var ($set,@set) = (0) loop $lin (grepFile($fil,'^\s*#','v')) {if match($lin,'^\s*A\s+') {var (undef,$hst,$usr,$sct,$pwd) = split('\s+',trim($lin),5) if !compare('eq',$hst,'-') next !?$hst = isHost($hst,true) next !?$usr = isUser($usr,true) next !match($sct,'^\w[\w\-\.]*$') call push(@set,incr($set)) var ${RUN.EXPLORER.XPLR.ILMB.T_HOST_${VAR.set}} = $hst var ${RUN.EXPLORER.XPLR.ILMB.T_USER_${VAR.set}} = $usr var ${RUN.EXPLORER.XPLR.ILMB.T_SECTION_${VAR.set}} = $sct # Save archive host password if ?$pwd call setPassword('host',cond(compare('eq',$hst,'-'),${RDA.T_HOST},$hst),\ $usr,$pwd) } elsif match($lin,'^\s*T\s+') {var (undef,$usr,$pwd) = split('\s+',trim($lin),3) # Save ILOM key password if ?$pwd call setPassword('host',$GRP,$usr,$pwd) } elsif match($lin,'^\s*I\s+') {var (undef,$hst,$usr,$pwd) = split('\s+',trim($lin),4) # Save ILOM host password if ?$pwd call setPassword('host',$hst,$usr,$pwd) } } # Save the parsing results if $set {var ${RUN.EXPLORER.XPLR.ILMB.F_CFG} = $fil var ${RUN.EXPLORER.XPLR.ILMB.N_SET} = [@set] var ${RUN.EXPLORER.B_USE_ILMB} = true } else var ${RUN.EXPLORER.B_USE_ILMB} = $flg } } # Parse the input file if and(defined($fil = ${ENV.EXP_ILOMSNAPSHOTINPUT_CONFIG}),\ defined(testFile('frs',catFile($fil)))) call parse_input(lastTestFile(),true) elsif ?testFile('frs',catFile(${RUN.EXPLORER.D_ETC},'ilomsnapshotinput.txt')) call parse_input(lastTestFile(),false) =head1 SEE ALSO L, L =head1 COPYRIGHT NOTICE Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. =head1 TRADEMARK NOTICE Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners. =cut