Skip to content

Commit 4c2b687

Browse files
committed
Add tool to compare built ipa and master ipa initramfs
Signed-off-by: peppi-lotta <peppi-lotta.saari@est.tech>
1 parent 1e0f3cf commit 4c2b687

File tree

1 file changed

+227
-0
lines changed

1 file changed

+227
-0
lines changed

hack/ipa_debug_tools.sh

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
#!/usr/bin/env bash
2+
3+
# The path to the directory that holds this script
4+
CURRENT_SCRIPT_DIR="$(dirname -- "$(readlink -f "${BASH_SOURCE[0]}")")"
5+
6+
# This ceates a minimal set up in /tmp/debug-initramfs directory for
7+
# comparing built ipa initramfs the master ipa initramfs.
8+
set_up_debug_dirs() {
9+
# Export DISABLE_UPLOAD, ENABLE_BOOTSTRAP_TEST, TEST_IN_CI to allow local
10+
# test run.
11+
export DISABLE_UPLOAD="true"
12+
export ENABLE_BOOTSTRAP_TEST="false"
13+
export TEST_IN_CI="false"
14+
15+
# Build ipa with build_ipa.sh
16+
cd "$CURRENT_SCRIPT_DIR/../jenkins/scripts/dynamic_worker_workflow" || exit
17+
if [[ ! -x ./build_ipa.sh ]]; then
18+
echo "Error: build_ipa.sh not found or not executable in $(pwd)"
19+
exit 1
20+
fi
21+
./build_ipa.sh
22+
23+
# Even if build_ipa.sh exits with error this script can continue as long as
24+
# /tmp/dib/ironic-python-agent.initramfs has been created
25+
if [[ ! -f /tmp/dib/ironic-python-agent.initramfs ]]; then
26+
exit 1
27+
fi
28+
29+
# Unzip ironic-python-agent.initramfs
30+
sudo mkdir -p /tmp/debug-initramfs/build-ipa-initramfs
31+
sudo cp /tmp/dib/ironic-python-agent.initramfs /tmp/debug-initramfs/
32+
cd /tmp/debug-initramfs/build-ipa-initramfs || exit
33+
gunzip -c ../ironic-python-agent.initramfs | sudo cpio -id
34+
35+
# Get master ironic-python-agent.initramfs and unzip
36+
sudo mkdir -p /tmp/debug-initramfs/master-ipa-initramfs
37+
cd /tmp/debug-initramfs || exit
38+
sudo wget https://tarballs.opendev.org/openstack/ironic-python-agent/dib/ipa-centos9-master.tar.gz
39+
sudo tar -xzf ipa-centos9-master.tar.gz
40+
cd master-ipa-initramfs || exit
41+
gunzip -c ../ipa-centos9-master.initramfs | sudo cpio -id
42+
}
43+
44+
# -----------------------------------------------------------------------------
45+
# compare_dir_sizes <relative_path> [base_dir1] [base_dir2]
46+
#
47+
# Compares the sizes of files and directories at the given <relative_path>
48+
# inside two extracted initramfs directories (or any two directories).
49+
#
50+
# Usage examples:
51+
# ./ipa_debug_tools.sh compare_dir_sizes
52+
# ./ipa_debug_tools.sh compare_dir_sizes usr
53+
# ./ipa_debug_tools.sh compare_dir_sizes usr/lib ~/ipa-build-initramfs ~/ipa-initramfs
54+
# ./ipa_debug_tools.sh compare_dir_sizes . ~/ipa-build-initramfs ~/ipa-initramfs
55+
#
56+
# - <relative_path>: Path inside the compared directories (e.g., usr, usr/lib)
57+
# - [base_dir1]: First base directory (default: /tmp/debug-initramfs/build-ipa-initramfs)
58+
# - [base_dir2]: Second base directory (default: /tmp/debug-initramfs/master-ipa-initramfs)
59+
#
60+
# The function prints a table of entries, their sizes in both directories,
61+
# and the size difference. It also lists files only present in one directory.
62+
# -----------------------------------------------------------------------------
63+
compare_dir_sizes() {
64+
path="${1:-}"
65+
basedir1="${2:-/tmp/debug-initramfs/build-ipa-initramfs}"
66+
basedir2="${3:-/tmp/debug-initramfs/master-ipa-initramfs}"
67+
68+
dir1="${basedir1}/${path}"
69+
dir2="${basedir2}/${path}"
70+
71+
# Color codes
72+
RED='\033[0;31m'
73+
GREEN='\033[0;32m'
74+
YELLOW='\033[1;33m'
75+
BLUE='\033[0;34m'
76+
PURPLE='\033[0;35m'
77+
CYAN='\033[0;36m'
78+
NC='\033[0m' # No Color
79+
BOLD='\033[1m'
80+
81+
echo -e "${CYAN}📊 Comparing directories:${NC}"
82+
echo -e " ${BLUE}🏗️ Build IPA:${NC} ${dir1}"
83+
echo -e " ${GREEN}🎯 Master IPA:${NC} ${dir2}"
84+
echo ""
85+
86+
# Print table header
87+
printf "${BOLD}%-40s %-22s %-22s %-22s${NC}\n" "Directory/File" "🏗️ Build" "🎯 Master" "📏 Diff"
88+
echo "======================================================================================================="
89+
90+
tmpfile=$(mktemp)
91+
checked=0
92+
skipped=0
93+
94+
# Compare entries present in both directories
95+
find "${dir1}" -mindepth 1 -maxdepth 1 -printf '%f\n' | sort > /tmp/dir1_list
96+
find "${dir2}" -mindepth 1 -maxdepth 1 -printf '%f\n' | sort > /tmp/dir2_list
97+
comm -12 /tmp/dir1_list /tmp/dir2_list | while IFS= read -r name; do
98+
# Get size in bytes for each entry
99+
bsize=$(du -sb "${dir1}/${name}" 2>/dev/null | cut -f1)
100+
isize=$(du -sb "${dir2}/${name}" 2>/dev/null | cut -f1)
101+
# Calculate absolute difference
102+
diff=$(( bsize > isize ? bsize - isize : isize - bsize ))
103+
echo -e "${name}\t${bsize}\t${isize}\t${diff}"
104+
done | sort -k4,4nr > "${tmpfile}"
105+
106+
# Print entries with size differences
107+
while IFS=$'\t' read -r name bsize isize diff; do
108+
checked=$((checked+1))
109+
if [[ "${diff}" -eq 0 ]]; then
110+
skipped=$((skipped+1))
111+
continue
112+
fi
113+
114+
# Color code based on size difference magnitude
115+
if [[ "${diff}" -gt 10485760 ]]; then # > 10MB
116+
diff_color="${RED}"
117+
icon="🔴"
118+
elif [[ "${diff}" -gt 1048576 ]]; then # > 1MB
119+
diff_color="${YELLOW}"
120+
icon="🟡"
121+
else
122+
diff_color="${GREEN}"
123+
icon="🟢"
124+
fi
125+
126+
printf "%-40s ${BLUE}%-22s${NC} ${GREEN}%-22s${NC} ${diff_color}%s %-21s${NC}\n" \
127+
"${name}" \
128+
"$(numfmt --to=iec "${bsize}")" \
129+
"$(numfmt --to=iec "${isize}")" \
130+
"${icon}" \
131+
"$(numfmt --to=iec "${diff}")"
132+
done < "$tmpfile"
133+
134+
echo -e "\n${PURPLE}📈 Summary:${NC} Checked ${BOLD}${checked}${NC} common entries, skipped ${BOLD}${skipped}${NC} identical sizes."
135+
echo "======================================================================================================="
136+
137+
rm -f "${tmpfile}"
138+
139+
# List files only in dir1
140+
echo -e "\n${BLUE}🏗️ Only in Build IPA (${dir1}):${NC}"
141+
echo "-------------------------------------------------------------------------------------------------------"
142+
comm -23 /tmp/dir1_list /tmp/dir2_list | while IFS= read -r name; do
143+
bsize=$(du -sb "${dir1}/${name}" 2>/dev/null | cut -f1)
144+
echo -e "${bsize}\t${name}"
145+
done | sort -k1,1nr | while IFS=$'\t' read -r bsize name; do
146+
printf "${BLUE}%-40s %-22s${NC}\n" "${name}" "$(numfmt --to=iec ${bsize})"
147+
done
148+
149+
echo "======================================================================================================="
150+
151+
# List files only in dir2
152+
echo -e "\n${GREEN}🎯 Only in Master IPA (${dir2}):${NC}"
153+
echo "-------------------------------------------------------------------------------------------------------"
154+
comm -13 /tmp/dir1_list /tmp/dir2_list | while IFS= read -r name; do
155+
isize=$(du -sb "${dir2}/${name}" 2>/dev/null | cut -f1)
156+
echo -e "${isize}\t${name}"
157+
done | sort -k1,1nr | while IFS=$'\t' read -r isize name; do
158+
printf "${GREEN}%-40s %-22s${NC}\n" "${name}" "$(numfmt --to=iec ${isize})"
159+
done
160+
161+
# Print some empty lines for clarity
162+
echo ""
163+
echo ""
164+
echo ""
165+
166+
# Remove temporary dir lists
167+
rm /tmp/dir1_list /tmp/dir2_list
168+
}
169+
170+
# Print a rpm package list. The print omits packages that are identical in both
171+
#the built ipa and master.
172+
# Check if packages are a part of CentOS Stream in https://pkgs.org
173+
compare_rpm_packages() {
174+
basedir1="${1:-/tmp/debug-initramfs/build-ipa-initramfs}"
175+
basedir2="${2:-/tmp/debug-initramfs/master-ipa-initramfs}"
176+
compfile1="/tmp/build-ipa-rpm.txt"
177+
compfile2="/tmp/master-ipa-rpm.txt"
178+
179+
sudo chroot "${basedir1}" rpm -qa | sort > "${compfile1}"
180+
sudo chroot "${basedir2}" rpm -qa | sort > "${compfile2}"
181+
182+
common_count=$(comm -12 "${compfile1}" "${compfile2}" | wc -l)
183+
echo -e "\nNumber of common packages: ${common_count}\n"
184+
# Extract base package names and join for fuzzy matching
185+
awk -F'-[0-9]' '{print $1}' "${compfile1}" | sort > /tmp/build-ipa-base.txt
186+
awk -F'-[0-9]' '{print $1}' "${compfile2}" | sort > /tmp/master-ipa-base.txt
187+
188+
printf "%-65s | %-65s\n" "In ${basedir1}" "In ${basedir2}"
189+
printf -- "----------------------------------------------------------------------------------------------------------------------------------\n"
190+
191+
join -a1 -a2 -e '' -o 1.1,2.1 /tmp/build-ipa-base.txt /tmp/master-ipa-base.txt | \
192+
while IFS=' ' read -r left right; do
193+
# Find the full package lines for each base name
194+
lfull=$(grep -m1 "^${left}-" "${compfile1}" || echo "")
195+
rfull=$(grep -m1 "^${right}-" "${compfile2}" || echo "")
196+
# Skip printing if both lines are non-empty and exactly the same
197+
if [[ -n "${lfull}" && "${lfull}" == "${rfull}" ]]; then
198+
continue
199+
fi
200+
printf "%-65s | %-65s\n" "${lfull}" "${rfull}"
201+
done
202+
203+
sudo rm -f "${compfile1}" "${compfile2}" /tmp/build-ipa-base.txt /tmp/master-ipa-base.txt
204+
}
205+
206+
# After debugging and comparison operations, temporary directories can be cleaned up.
207+
# Usage:
208+
# ./ipa_debug_tools.sh clean_up_debug_dirs
209+
# -----------------------------------------------------------------------------
210+
clean_up_debug_dirs() {
211+
# Clean up debug directories
212+
sudo rm -rf /tmp/debug-initramfs
213+
}
214+
215+
# Allow calling functions
216+
# -----------------------------------------------------------------------------
217+
function_name="$1"
218+
shift
219+
220+
# Check if function exists and call it
221+
if declare -f "$function_name" > /dev/null; then
222+
"$function_name" "$@"
223+
else
224+
echo "Error: Function '$function_name' not found"
225+
echo "Available functions: set_up_debug_dirs, compare_dir_sizes, compare_rpm_packages, clean_up_debug_dirs"
226+
exit 1
227+
fi

0 commit comments

Comments
 (0)