315 lines
8.7 KiB
Bash
315 lines
8.7 KiB
Bash
#!/bin/bash
|
|
# Authors: Dalibor Pospíšil <dapospis@redhat.com>
|
|
# Author: Dalibor Pospisil <dapospis@redhat.com>
|
|
#
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
#
|
|
# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
|
|
#
|
|
# This copyrighted material is made available to anyone wishing
|
|
# to use, modify, copy, or redistribute it subject to the terms
|
|
# and conditions of the GNU General Public License version 2.
|
|
#
|
|
# This program is distributed in the hope that it will be
|
|
# useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
# PURPOSE. See the GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public
|
|
# License along with this program; if not, write to the Free
|
|
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
# Boston, MA 02110-1301, USA.
|
|
#
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# library-prefix = Cleanup
|
|
# library-version = 9
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
__INTERNAL_Cleanup_LIB_VERSION=9
|
|
: <<'=cut'
|
|
=pod
|
|
|
|
=head1 NAME
|
|
|
|
BeakerLib library Cleanup
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
This file contains functions which provides cleanup stack functionality.
|
|
|
|
=head1 USAGE
|
|
|
|
To use this functionality you need to import library distribution/Cleanup and add
|
|
following line to Makefile.
|
|
|
|
@echo "RhtsRequires: library(distribution/Cleanup)" >> $(METADATA)
|
|
|
|
B<Code example>
|
|
|
|
rlJournalStart
|
|
rlPhaseStartSetup
|
|
rlImport 'distribution/Cleanup'
|
|
tmp=$(mktemp)
|
|
CleanupRegister "
|
|
rlLog 'Removing data'
|
|
rlRun \"rm -f ${tmp}\"
|
|
"
|
|
rlLog 'Creating some data'
|
|
rlRun "echo 'asdfalkjh' > $tmp"
|
|
|
|
CleanupRegister "
|
|
rlLog 'just something to demonstrate unregistering'
|
|
"
|
|
ID1=$CleanupRegisterID
|
|
CleanupUnregister $ID1
|
|
|
|
CleanupRegister "
|
|
rlLog 'just something to demonstrate partial cleanup'
|
|
"
|
|
ID2=$CleanupRegisterID
|
|
CleanupRegister "rlLog 'cleanup some more things'"
|
|
# cleanup everything upto ID2
|
|
CleanupDo $ID2
|
|
|
|
CleanupRegister --mark "
|
|
rlLog 'yet another something to demonstrate partial cleanup using internal ID saving'
|
|
"
|
|
CleanupRegister "rlLog 'cleanup some more things'"
|
|
# cleanup everything upto last mark
|
|
CleanupDo --mark
|
|
rlPhaseEnd
|
|
|
|
rlPhaseStartCleanup
|
|
CleanupDo
|
|
rlPhaseEnd
|
|
|
|
rlJournalPrintText
|
|
rlJournalEnd
|
|
|
|
=head1 FUNCTIONS
|
|
|
|
=cut
|
|
|
|
echo -n "loading library Cleanup v$__INTERNAL_Cleanup_LIB_VERSION... "
|
|
|
|
__INTERNAL_Cleanup_stack_file="$BEAKERLIB_DIR/Cleanup_stack"
|
|
touch "$__INTERNAL_Cleanup_stack_file"
|
|
chmod ug+rw "$__INTERNAL_Cleanup_stack_file"
|
|
|
|
# CleanupRegister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
|
|
# CleanupRegister [--mark] CLEANUP_CODE
|
|
# --mark - also mark this position
|
|
CleanupRegister() {
|
|
local mark=0
|
|
[[ "$1" == "--mark" ]] && {
|
|
mark=1
|
|
shift
|
|
}
|
|
if ! CleanupGetStack; then
|
|
rlLogError "cannot continue, could not get cleanup stack"
|
|
return 1
|
|
fi
|
|
CleanupRegisterID="${RANDOM}$(date +"%s%N")"
|
|
echo -n "Registering cleanup ID=$CleanupRegisterID" >&2
|
|
if [[ $mark -eq 1 ]]; then
|
|
__INTERNAL_CleanupMark=( "$CleanupRegisterID" "${__INTERNAL_CleanupMark[@]}" )
|
|
echo -n " with mark" >&2
|
|
fi
|
|
echo " '$1'" >&2
|
|
rlLogDebug "prepending '$1'"
|
|
local ID_tag="# ID='$CleanupRegisterID'"
|
|
__INTERNAL_Cleanup_stack="$ID_tag
|
|
$1
|
|
$ID_tag
|
|
$__INTERNAL_Cleanup_stack"
|
|
if ! CleanupSetStack "$__INTERNAL_Cleanup_stack"; then
|
|
rlLogError "an error occured while registering the cleanup '$1'"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}; # end of CleanupRegister }}}
|
|
|
|
|
|
# __INTERNAL_Cleanup_get_stack_part ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
|
|
# 1: ID
|
|
# -ID - everything upto the ID
|
|
# 2: '' - return ID only
|
|
# 'rest' - return exact oposit
|
|
__INTERNAL_Cleanup_get_stack_part() {
|
|
rlLogDebug "__INTERNAL_Cleanup_get_stack_part(): $* begin"
|
|
local ID="$1"
|
|
local n='1 0 1'
|
|
local stack=''
|
|
[[ "${ID:0:1}" == "-" ]] && {
|
|
ID="${ID:1}"
|
|
n='0 0 1'
|
|
}
|
|
[[ "$2" == "rest" ]] && {
|
|
n="$(echo "${n//0/2}")"
|
|
n="$(echo "${n//1/0}")"
|
|
n="$(echo "${n//2/1}")"
|
|
}
|
|
n=($n)
|
|
[[ -n "$DEBUG" ]] && rlLogDebug "$(set | grep ^n=)"
|
|
local ID_tag="# ID='$ID'"
|
|
while IFS= read -r line; do
|
|
|
|
[[ "$line" == "$ID_tag" ]] && {
|
|
n=( "${n[@]:1}" )
|
|
continue
|
|
}
|
|
if [[ $n -eq 0 ]]; then
|
|
stack="$stack
|
|
$line"
|
|
fi
|
|
done < <(echo "$__INTERNAL_Cleanup_stack")
|
|
rlLogDebug "__INTERNAL_Cleanup_get_stack_part(): cleanup stack part is '${stack:1}'"
|
|
echo "${stack:1}"
|
|
rlLogDebug "__INTERNAL_Cleanup_get_stack_part(): $* end"
|
|
}; # end of __INTERNAL_Cleanup_get_stack_part }}}
|
|
|
|
# CleanupUnregister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
|
|
CleanupUnregister() {
|
|
local ID="$1"
|
|
rlLog "Unregistering cleanup ID='$ID'"
|
|
if ! CleanupGetStack; then
|
|
rlLogError "cannot continue, could not get cleanup stack"
|
|
return 1
|
|
fi
|
|
rlLogDebug "removing ID='$ID'"
|
|
if ! CleanupSetStack "$(__INTERNAL_Cleanup_get_stack_part "$ID" 'rest')"; then
|
|
rlLogError "an error occured while registering the cleanup '$1'"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}; # end of CleanupUnregister }}}
|
|
|
|
|
|
# CleanupMark ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
|
|
__INTERNAL_CleanupMark=()
|
|
CleanupMark() {
|
|
echo -n "Setting cleanup mark" >&2
|
|
CleanupRegister --mark '' 2>/dev/null
|
|
local res=$?
|
|
echo " ID='$CleanupRegisterID'" >&2
|
|
return $res
|
|
}; # end of CleanupMark }}}
|
|
|
|
|
|
# CleanupDo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
|
|
# 1: '' - cleanup all
|
|
# ID - cleanup ID only
|
|
# -ID - cleanup all upto ID, including
|
|
# mark - cleanup all unto last mark, including
|
|
CleanupDo() {
|
|
local ID="$1"
|
|
if ! CleanupGetStack; then
|
|
rlLogError "cannot continue, could not get cleanup stack"
|
|
return 1
|
|
fi
|
|
local res tmp newstack=''
|
|
tmp="$(mktemp)"
|
|
if [[ "$ID" == "mark" || "$ID" == "--mark" ]]; then
|
|
echo "execute cleanup upto mark='$__INTERNAL_CleanupMark'" >&2
|
|
__INTERNAL_Cleanup_get_stack_part "-$__INTERNAL_CleanupMark" | grep -v "^# ID='" > "$tmp"
|
|
newstack="$(__INTERNAL_Cleanup_get_stack_part "-$__INTERNAL_CleanupMark" 'rest')"
|
|
__INTERNAL_CleanupMark=("${__INTERNAL_CleanupMark[@]:1}")
|
|
elif [[ -n "$ID" ]]; then
|
|
echo "execute cleanup for ID='$ID'" >&2
|
|
__INTERNAL_Cleanup_get_stack_part "$ID" | grep -v "^# ID='" > "$tmp"
|
|
newstack="$(__INTERNAL_Cleanup_get_stack_part "$ID" 'rest')"
|
|
else
|
|
CleanupTrapUnhook
|
|
trap "echo 'temporarily blocking ctrl+c until cleanup is done' >&2" SIGINT
|
|
cat "$__INTERNAL_Cleanup_stack_file" | grep -v "^# ID='" > "$tmp"
|
|
echo "execute whole cleanup stack" >&2
|
|
fi
|
|
. "$tmp"
|
|
res=$?
|
|
[[ $res -ne 0 ]] && {
|
|
echo "cleanup code:" >&2
|
|
cat -n "$tmp" >&2
|
|
}
|
|
rm -f "$tmp"
|
|
echo "cleanup execution done" >&2
|
|
if [[ -z "$ID" ]]; then
|
|
trap - SIGINT
|
|
fi
|
|
if ! CleanupSetStack "$newstack"; then
|
|
rlLogError "an error occured while cleaning the stack"
|
|
return 1
|
|
fi
|
|
return $res
|
|
}; # end of CleanupDo }}}
|
|
|
|
|
|
# CleanupGetStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
|
|
CleanupGetStack() {
|
|
rlLogDebug "getting cleanup stack"
|
|
if [[ -r "$__INTERNAL_Cleanup_stack_file" ]]; then
|
|
if __INTERNAL_Cleanup_stack="$(cat "$__INTERNAL_Cleanup_stack_file")"; then
|
|
rlLogDebug "cleanup stack is '$__INTERNAL_Cleanup_stack'"
|
|
return 0
|
|
fi
|
|
fi
|
|
rlLogError "could not load cleanup stack"
|
|
return 1
|
|
}; # end of CleanupGetStack }}}
|
|
|
|
|
|
# CleanupSetStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
|
|
CleanupSetStack() {
|
|
rlLogDebug "setting cleanup stack to '$1'"
|
|
__INTERNAL_Cleanup_stack="$1"
|
|
if echo "$__INTERNAL_Cleanup_stack" > "$__INTERNAL_Cleanup_stack_file"; then
|
|
rlLogDebug "cleanup stack is now '$__INTERNAL_Cleanup_stack'"
|
|
return 0
|
|
fi
|
|
rlLogError "could not set cleanup stack"
|
|
return 1
|
|
}; # end of CleanupSetStack }}}
|
|
|
|
|
|
__INTERNAL_Cleanup_signals=''
|
|
__INTERNAL_Cleanup_trap_code='rlJournalStart; rlPhaseStartCleanup; CleanupDo; rlPhaseEnd; rlJournalPrintText; rlJournalEnd; exit'
|
|
# CleanupTrapHook ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
|
|
CleanupTrapHook() {
|
|
rlLog "register cleanup trap"
|
|
__INTERNAL_Cleanup_signals="${1:-"SIGHUP SIGINT SIGTERM EXIT"}"
|
|
eval "trap \"${__INTERNAL_Cleanup_trap_code}\" $__INTERNAL_Cleanup_signals"
|
|
}; # end of CleanupTrapHook }}}
|
|
|
|
|
|
# CleanupTrapUnhook ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
|
|
CleanupTrapUnhook() {
|
|
if [[ -n "$__INTERNAL_Cleanup_signals" ]]; then
|
|
rlLog "unregister cleanup trap"
|
|
eval trap - $__INTERNAL_Cleanup_signals
|
|
__INTERNAL_Cleanup_signals=''
|
|
fi
|
|
}; # end of CleanupTrapUnhook }}}
|
|
|
|
|
|
# CleanupLibraryLoaded ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {{{
|
|
CleanupLibraryLoaded() {
|
|
CleanupTrapHook
|
|
}; # end of CleanupLibraryLoaded }}}
|
|
|
|
|
|
echo "done."
|
|
|
|
: <<'=cut'
|
|
=pod
|
|
|
|
=head1 AUTHORS
|
|
|
|
=over
|
|
|
|
=item *
|
|
|
|
Dalibor Pospisil <dapospis@redhat.com>
|
|
|
|
=back
|
|
|
|
=cut
|
|
|