forked from openstack/openstack-ansible-tests
-
Notifications
You must be signed in to change notification settings - Fork 1
/
test-log-collect.sh
executable file
·295 lines (255 loc) · 11.5 KB
/
test-log-collect.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
#!/usr/bin/env bash
# Copyright 2016, Rackspace US, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# WARNING:
# This file is use by all OpenStack-Ansible roles for testing purposes.
# Any changes here will affect all OpenStack-Ansible role repositories
# with immediate effect.
# PURPOSE:
# This script collects, renames and compresses the logs produced in
# a role test if the host is in OpenStack-CI.
## Vars ----------------------------------------------------------------------
export WORKING_DIR=${WORKING_DIR:-$(pwd)}
export TESTING_HOME=${TESTING_HOME:-$HOME}
export RSYNC_CMD="rsync --archive --copy-links --ignore-errors --quiet --no-perms --no-owner --no-group --whole-file --inplace"
# NOTE(cloudnull): This is a very simple list of common directories in /etc we
# wish to search for when storing gate artifacts. When adding
# things to this list please alphabetize the entries so it's
# easy for folks to find and adjust items as needed.
COMMON_ETC_LOG_NAMES="almanach \
apt \
aodh \
apache2 \
barbican \
blazar \
ceilometer \
cinder \
cloudkitty \
congress \
designate \
glance \
gnocchi \
haproxy \
heat \
horizon \
httpd \
ironic \
karbor \
keystone \
magnum \
manila \
memcached \
molteniron \
monasca \
mongodb \
my.cnf \
mysql \
netplan \
network \
nginx \
neutron \
nova \
octavia \
panko \
pip.conf \
qpid-dispatch \
rabbitmq \
rally \
repo \
resolv.conf \
rsyslog \
sahara \
searchlight \
sasl2 \
swift \
sysconfig/network-scripts \
sysconfig/network \
systemd/network \
tacker \
tempest \
trove \
watcher \
yum \
yum.repos.d \
zaqar \
zun \
zypp"
## Functions -----------------------------------------------------------------
function repo_information {
[[ "${1}" != "host" ]] && lxc_cmd="lxc-attach --name ${1} --" || lxc_cmd=""
echo "Collecting list of installed packages and enabled repositories for \"${1}\""
# Redhat package debugging
if eval sudo ${lxc_cmd} which yum &>/dev/null || eval sudo ${lxc_cmd} which dnf &>/dev/null; then
# Prefer dnf over yum for CentOS.
eval sudo ${lxc_cmd} which dnf &>/dev/null && RHT_PKG_MGR='dnf' || RHT_PKG_MGR='yum'
eval sudo ${lxc_cmd} $RHT_PKG_MGR repolist -v > "${WORKING_DIR}/logs/redhat-rpm-repolist-${1}.txt" || true
eval sudo ${lxc_cmd} $RHT_PKG_MGR list installed > "${WORKING_DIR}/logs/redhat-rpm-list-installed-${1}.txt" || true
# SUSE package debugging
elif eval sudo ${lxc_cmd} which zypper &>/dev/null; then
eval sudo ${lxc_cmd} zypper lr -d > "${WORKING_DIR}/logs/suse-zypper-repolist-${1}.txt" || true
eval sudo ${lxc_cmd} zypper --disable-repositories pa -i > "${WORKING_DIR}/logs/suse-zypper-list-installed-${1}.txt" || true
# Ubuntu package debugging
elif eval sudo ${lxc_cmd} which apt-get &> /dev/null; then
eval sudo ${lxc_cmd} apt-cache policy | grep http | awk '{print $1" "$2" "$3}' | sort -u > "${WORKING_DIR}/logs/ubuntu-apt-repolist-${1}.txt" || true
eval sudo ${lxc_cmd} apt list --installed > "${WORKING_DIR}/logs/ubuntu-apt-list-installed-${1}.txt" || true
# Gentoo package debugging
elif eval sudo ${lxc_cmd} which emerge &> /dev/null; then
# list installed packages
eval sudo ${lxc_cmd} equery list "*" > "${WORKING_DIR}/logs/gentoo-portage-list-installed-${1}.txt" || true
# list only packages called for install (not dependancies)
eval sudo ${lxc_cmd} cat /var/lib/portage/world > "${WORKING_DIR}/logs/gentoo-portage-list-manual-installed-${1}.txt" || true
fi
}
function store_artifacts {
# Store known artifacts only if they exist. If the target directory does
# exist, it will be created.
# USAGE: store_artifacts /src/to/artifacts /path/to/store
if sudo test -e "${1}"; then
if [[ ! -d "${2}" ]]; then
mkdir -vp "${2}"
fi
echo "Running artifact sync for \"${1}\" to \"${2}\""
sudo ${RSYNC_CMD} ${1} ${2} || true
fi
}
function store_journal_artifacts {
# Store lines from a known unit's journal as a plain-text log file.
# USAGE: store_journal_artifacts UNIT_TO_MATCH /path/to/store
if [ $? == 0 ]; then
if [[ ! -d "${2}" ]]; then
mkdir -vp "${2}"
fi
if [[ ${3:-false} != false ]]; then
if [[ -f "/var/log/journal/${3}/system.journal" ]]; then
SYSTEMD_UNITS=$(sudo journalctl --file="/var/log/journal/${3}/system.journal" \
--output=json-pretty | grep -w UNIT | sort -u | awk -F'"' '{print $4}' | grep "${1}")
for service_unit in $(echo -e "${SYSTEMD_UNITS}"); do
echo "Pulling journal for ${service_unit}"
sudo journalctl --file="/var/log/journal/${3}/system.journal" \
--since="1 hour ago" \
--unit="${service_unit}" | sudo tee "${2}/${service_unit}.journal.log" &>/dev/null
done
fi
else
SYSTEMD_UNITS=$(sudo journalctl --output=json-pretty | grep -w UNIT | sort -u | awk -F'"' '{print $4}' | grep "${1}")
for service_unit in $(echo -e "${SYSTEMD_UNITS}"); do
echo "Pulling journal for ${service_unit}"
sudo journalctl --since="1 hour ago" \
--unit="${service_unit}" | sudo tee "${2}/${service_unit}.journal.log" &>/dev/null
done
fi
fi
}
function find_files {
find "${WORKING_DIR}/logs/" -type f \
! -name "*.gz" \
! -name '*.html' \
! -name '*.subunit' \
! -name "*.journal" \
! -name 'ansible.sqlite' | grep -v 'stackviz'
}
function rename_files {
find_files |\
while read filename; do \
mv ${filename} ${filename}.txt || echo "WARNING: Could not rename ${filename}"; \
done
}
function compress_files {
# We use 'command' to ensure that we're not executing with an alias.
GZIP_CMD="command gzip --force --best"
find_files |\
while read filename; do \
${GZIP_CMD} ${filename} || echo "WARNING: Could not gzip ${filename}"; \
done
}
## Main ----------------------------------------------------------------------
echo "#### BEGIN LOG COLLECTION ###"
mkdir -vp "${WORKING_DIR}/logs"
# Gather basic logs
store_artifacts /openstack/log/ansible-logging/ "${WORKING_DIR}/logs/ansible"
store_artifacts /openstack/log/ "${WORKING_DIR}/logs/openstack"
store_artifacts /var/log/ "${WORKING_DIR}/logs/host"
# Store the ara sqlite database in the openstack-ci expected path
store_artifacts "${TESTING_HOME}/.ara/ansible.sqlite" "${WORKING_DIR}/logs/ara-report/"
# Store netstat report
store_artifacts /tmp/listening_port_report.txt "${WORKING_DIR}/logs/host"
# Verify the integrity of the journal files but do not fail if one of them is not usable
echo "Verifying journal files consistency..."
find /var/log/journal/ -type f -name "*.journal" -exec bash -c 'sudo journalctl --file={} --verify || true' \;
# Gather host etc artifacts
for service in ${COMMON_ETC_LOG_NAMES}; do
store_artifacts "/etc/${service}" "${WORKING_DIR}/logs/etc/host/"
store_journal_artifacts "${service}" "${WORKING_DIR}/logs/host"
done
# Gather container etc artifacts
if which lxc-ls &> /dev/null; then
for CONTAINER_NAME in $(sudo lxc-ls -1); do
CONTAINER_PID=$(sudo lxc-info -p -n ${CONTAINER_NAME} | awk '{print $2}')
ETC_DIR="/proc/${CONTAINER_PID}/root/etc"
MACHINE_ID="$(sudo cat ${ETC_DIR}/machine-id)"
LOG_DIR="/proc/${CONTAINER_PID}/root/var/log"
repo_information ${CONTAINER_NAME}
for service in ${COMMON_ETC_LOG_NAMES}; do
store_artifacts ${ETC_DIR}/${service} "${WORKING_DIR}/logs/etc/openstack/${CONTAINER_NAME}/"
store_artifacts ${LOG_DIR}/${service} "${WORKING_DIR}/logs/openstack/${CONTAINER_NAME}/"
store_journal_artifacts ${service} "${WORKING_DIR}/logs/openstack/${CONTAINER_NAME}" "${MACHINE_ID}"
done
done
fi
# NOTE(mhayden): All of the files must be world-readable so that the log
# pickup jobs will work properly. Without this, you get a "File not found"
# when trying to read the files in the job results.
# NOTE(odyssey4me): Using '--chown $(whoami) --chmod=ugo+rX' in the rsync
# CMD to achieve this would be optimal, but the CentOS version of rsync
# (3.0.x) does not support that option.
sudo chmod -R ugo+rX "${WORKING_DIR}/logs/"
sudo chown -R $(whoami) "${WORKING_DIR}/logs/"
# Rename all files gathered to have a .txt suffix so that the compressed
# files are viewable via a web browser in OpenStack-CI.
rename_files
# Figure out the correct path for ARA
# As this script is not run through tox, and the tox envs are all
# different names, we need to try and find the right path to execute
# ARA from.
ARA_CMD="$(find ${WORKING_DIR}/.tox -path "*/bin/ara" -type f | head -n 1)"
# If we could not find ARA, assume it was not installed
# and skip all the related activities.
if [[ "${ARA_CMD}" != "" ]]; then
# Generate the ARA subunit report so that the
# results reflect in OpenStack-Health
mkdir -vp "${WORKING_DIR}/logs/ara-data"
echo "Generating ARA report subunit report."
${ARA_CMD} generate subunit "${WORKING_DIR}/logs/ara-data/testrepository.subunit" || true
fi
# Get a dmesg output so we can look for kernel failures
dmesg > "${WORKING_DIR}/logs/dmesg.log.txt" || true
# Collect job environment
env > "${WORKING_DIR}/logs/environment.txt" || true
# output ram usage
free -m > "${WORKING_DIR}/logs/memory-available.txt" || true
# iptables
sudo iptables -nvL > "${WORKING_DIR}/logs/iptables.txt" || true
sudo iptables -t nat -nvL > "${WORKING_DIR}/logs/iptables-nat.txt" || true
repo_information host
# Record the active interface configs
for interface in $(ip -o link | awk -F':' '{print $2}'); do
if which ethtool &> /dev/null; then
ethtool -k ${interface} > "${WORKING_DIR}/logs/ethtool-${interface}-cfg.txt" || true
else
echo "No ethtool available" | tee -a "${WORKING_DIR}/logs/ethtool-${interface}-cfg.txt"
fi
done
# Compress the files gathered so that they do not take up too much space.
compress_files
echo "#### END LOG COLLECTION ###"