Merge ~hopem/ua-reviewkit:bug/1896376 into ua-reviewkit:master

Proposed by Edward Hope-Morley
Status: Merged
Merged at revision: 24e89560c88a236c83121fc88098bab0cafef44a
Proposed branch: ~hopem/ua-reviewkit:bug/1896376
Merge into: ua-reviewkit:master
Diff against target: 461 lines (+229/-191)
3 files modified
openstack/extra-checks.d/glance (+76/-0)
openstack/extra-checks.d/octavia (+147/-0)
openstack/openstack-extra-checks.sh (+6/-191)
Reviewer Review Type Date Requested Status
UA Reviewers Pending
Review via email: mp+393107@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/openstack/extra-checks.d/glance b/openstack/extra-checks.d/glance
2new file mode 100755
3index 0000000..ae0d9c5
4--- /dev/null
5+++ b/openstack/extra-checks.d/glance
6@@ -0,0 +1,76 @@
7+#!/bin/bash -eu
8+# Copyright 2020 Canonical Ltd
9+#
10+# Licensed under the Apache License, Version 2.0 (the "License");
11+# you may not use this file except in compliance with the License.
12+# You may obtain a copy of the License at
13+#
14+# http://www.apache.org/licenses/LICENSE-2.0
15+#
16+# Unless required by applicable law or agreed to in writing, software
17+# distributed under the License is distributed on an "AS IS" BASIS,
18+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19+# See the License for the specific language governing permissions and
20+# limitations under the License.
21+#
22+# Authors:
23+# - edward.hope-morley@canonical.com
24+
25+# Checks to see if Ceph backend is used in either Nova or Cinder and if it
26+# is, checks that all images in Glance have disk_format=raw.
27+# See the following KB article for information on why this is important:
28+# https://support.canonical.com/ua/s/article/openstack-boot-image-considerations
29+
30+rc=0
31+ftmp=`mktemp`
32+
33+exists="`juju status --format=json| jq '.applications| to_entries[]| select(.value.charm| test(\".+ceph-mon.+\"))'`"
34+if [ -z "$exists" ]; then
35+ echo "INFO: no ceph-mon found - skipping test"
36+ rm $ftmp
37+ exit 0
38+fi
39+
40+juju status ceph-mon --format=json > $ftmp
41+readarray -t clients<<<"`jq -r '.applications."ceph-mon".relations.client[]' $ftmp`"
42+if ((${#clients[@]})) && [ -n "${clients[0]}" ]; then
43+ raw_required=false
44+ for client in ${clients[@]}; do
45+ if [[ $client =~ nova-compute.* ]] ||
46+ [[ $client =~ cinder-ceph.* ]]; then
47+ raw_required=true
48+ break
49+ fi
50+ done
51+ if $raw_required; then
52+ openstack image list --long -c ID -c 'Disk Format' -f value > $ftmp
53+ if ((`awk '{print $2}' $ftmp| sort -u| wc -l` > 1)); then
54+cat << EOF
55+WARNING: not all images in Glance have disk_format=raw
56+
57+Your environment is using Ceph as a backend for one or both of nova-compute
58+or cinder and as a result it is essential to use images with raw format in
59+order to avoid a large capacity and performance impact on your cloud and ceph
60+cluster. This format is also needed in order to benefit from Copy-on-Write
61+cloning of images in both Cinder and Nova.
62+
63+For more information on why this is important please see the following article:
64+
65+https://support.canonical.com/ua/s/article/openstack-boot-image-considerations
66+EOF
67+ echo -e "\nImage format details:"
68+ readarray -t formats<<<"`sort -k 2 $ftmp| awk '{print $2}'| uniq`"
69+ for fmt in ${formats[@]}; do
70+ awk "\$2==\"$fmt\" {print \$2}" $ftmp| sort| uniq -c
71+ done
72+ echo ""
73+ rc=1
74+ fi
75+ else
76+ echo "No hard requirement for raw images - skipping check"
77+ fi
78+fi
79+
80+rm $ftmp
81+exit $rc
82+
83diff --git a/openstack/extra-checks.d/octavia b/openstack/extra-checks.d/octavia
84new file mode 100755
85index 0000000..bb976df
86--- /dev/null
87+++ b/openstack/extra-checks.d/octavia
88@@ -0,0 +1,147 @@
89+#!/bin/bash -eu
90+# Copyright 2020 Canonical Ltd
91+#
92+# Licensed under the Apache License, Version 2.0 (the "License");
93+# you may not use this file except in compliance with the License.
94+# You may obtain a copy of the License at
95+#
96+# http://www.apache.org/licenses/LICENSE-2.0
97+#
98+# Unless required by applicable law or agreed to in writing, software
99+# distributed under the License is distributed on an "AS IS" BASIS,
100+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
101+# See the License for the specific language governing permissions and
102+# limitations under the License.
103+#
104+# Authors:
105+# - edward.hope-morley@canonical.com
106+
107+MAX_WAIT_ACTIVE=50
108+
109+_delete_lb ()
110+{
111+ openstack loadbalancer delete --cascade $1
112+}
113+
114+active_wait_timeout ()
115+{
116+ local lb_id=$1
117+ echo "ERROR: reached MAX_WAIT_ACTIVE ($MAX_WAIT_ACTIVE)"
118+ _delete_lb $lb_id
119+ exit 1
120+}
121+
122+## OCTAVIA LOADBALANCER TEST
123+#
124+# This test requires project net, subnet, ext net and vm. These can be
125+# provided using env vars otherwise input is requested.
126+#
127+# export UA_OS_CHECKS_PROJECT_NET=<tenant network name or uuid>
128+# export UA_OS_CHECKS_PROJECT_SUBNET=<tenant subnet name or uuid>
129+# export UA_OS_CHECKS_EXT_NET=<external net name or uuid>
130+# export UA_OS_CHECKS_VM_UUID=<vm uuid>
131+
132+rc=0
133+net=
134+subnet=
135+ext_net=
136+member_vm=
137+test_tag=`uuidgen`
138+lb_name=test-lb-${test_tag}
139+
140+exists="`juju status --format=json| jq '.applications| to_entries[]| select(.value.charm| test(\".+octavia.+\"))'`"
141+if [ -z "$exists" ]; then
142+ echo "INFO: no octavia found - skipping test"
143+ exit 0
144+fi
145+
146+if [ -n "${UA_OS_CHECKS_PROJECT_NET:-}" ]; then
147+ net=$UA_OS_CHECKS_PROJECT_NET
148+else
149+ read -p "Tenant network name to use for Octavia LB test: " net
150+fi
151+if [ -n "${UA_OS_CHECKS_PROJECT_SUBNET:-}" ]; then
152+ subnet=$UA_OS_CHECKS_PROJECT_SUBNET
153+else
154+ read -p "Tenant subnet name to use for Octavia LB test: " subnet
155+fi
156+if [ -n "${UA_OS_CHECKS_EXT_NET:-}" ]; then
157+ ext_net=$UA_OS_CHECKS_EXT_NET
158+else
159+ read -p "External net to use for Octavia LB test: " ext_net
160+fi
161+if [ -n "${UA_OS_CHECKS_VM_UUID:-}" ]; then
162+ member_vm=$UA_OS_CHECKS_VM_UUID
163+else
164+ read -p "UUID of guest vm with something listening on port 80 (e.g. apache): " member_vm
165+fi
166+
167+echo "Creating loadbalancer $lb_name..."
168+lb_id=`openstack loadbalancer create --name $lb_name --vip-subnet-id $subnet -c id -f value`
169+wait_cycle=0
170+while true; do
171+ ((wait_cycle++ < MAX_WAIT_ACTIVE)) || active_wait_timeout
172+ status="`openstack loadbalancer show $lb_id -c provisioning_status -f value`"
173+ [ "$status" = "ACTIVE" ] && break
174+ [ "$status" = "ERROR" ] && { _delete_lb $lb_id; exit 1; }
175+ echo "Waiting for LB $lb_name (uuid=$lb_id) to be ACTIVE (current=$status)"
176+done
177+openstack loadbalancer listener create --name test-listener-${test_tag} --protocol HTTP --protocol-port 80 $lb_id
178+wait_cycle=0
179+while true; do
180+ ((wait_cycle++ < MAX_WAIT_ACTIVE)) || active_wait_timeout $lb_id
181+ status="`openstack loadbalancer listener show test-listener-${test_tag} -c provisioning_status -f value`"
182+ [ "$status" = "ACTIVE" ] && break
183+ [ "$status" = "ERROR" ] && { _delete_lb $lb_id; exit 1; }
184+ echo "Waiting for Listener test-listener-${test_tag} to be ACTIVE (current=$status)"
185+done
186+openstack loadbalancer pool create --name test-pool-${test_tag} --lb-algorithm ROUND_ROBIN --listener test-listener-${test_tag} --protocol HTTP
187+wait_cycle=0
188+while true; do
189+ ((wait_cycle++ < MAX_WAIT_ACTIVE)) || active_wait_timeout $lb_id
190+ status="`openstack loadbalancer pool show test-pool-${test_tag} -c provisioning_status -f value`"
191+ [ "$status" = "ACTIVE" ] && break
192+ [ "$status" = "ERROR" ] && { _delete_lb $lb_id; exit 1; }
193+ echo "Waiting for test-pool-${test_tag} to be ACTIVE (current=$status)"
194+done
195+openstack loadbalancer healthmonitor create --delay 5 --max-retries 4 --timeout 10 --type HTTP --url-path / test-pool-${test_tag}
196+openstack loadbalancer healthmonitor list
197+if [ -n "$member_vm" ]; then
198+ netaddr=$(openstack port list --server $member_vm --network $net \
199+ -c "Fixed IP Addresses" -f value | sed -r "s/.*ip_address(=|':\s+)'([[:digit:]\.]+)'.*/\2/g")
200+ member_id=$(openstack loadbalancer member create --subnet-id $subnet \
201+ --address $netaddr --protocol-port 80 --format value --column id test-pool-${test_tag})
202+ wait_cycle=0
203+ while true; do
204+ ((wait_cycle++ < MAX_WAIT_ACTIVE)) || active_wait_timeout $lb_id
205+ status="`openstack loadbalancer member show -f value -c provisioning_status test-pool-${test_tag} $member_id`"
206+ [ "$status" = ACTIVE ] && break
207+ [ "$status" = "ERROR" ] && { _delete_lb $lb_id; exit 1; }
208+ echo "Waiting for member $member_vm ($member_id) to be ACTIVE (current=$status)"
209+ done
210+
211+ openstack loadbalancer member list test-pool-${test_tag}
212+
213+ fip=`openstack floating ip create -f value -c floating_ip_address $ext_net`
214+ lb_vip_port_id=$(openstack loadbalancer show -f value -c vip_port_id $lb_id)
215+ openstack floating ip set --port $lb_vip_port_id $fip
216+ # NOTE: floating ip may not be immediately available
217+ retry_count=10
218+ while ! ((rc)); do
219+ rc=0
220+ nc -w 5 -vz $fip 80 || rc=$?
221+ if ((rc)) && ((retry_count>0)); then
222+ rc=0
223+ ((retry_count--))
224+ echo "retrying.."
225+ sleep 1
226+ else
227+ echo "ERROR: max retries reached, could not connect to lb fip"
228+ break
229+ fi
230+ done
231+fi
232+
233+_delete_lb $lb_id
234+exit $rc
235+
236diff --git a/openstack/openstack-extra-checks.sh b/openstack/openstack-extra-checks.sh
237index 85597a4..e69c621 100755
238--- a/openstack/openstack-extra-checks.sh
239+++ b/openstack/openstack-extra-checks.sh
240@@ -1,4 +1,4 @@
241-#!/bin/bash
242+#!/bin/bash -u
243 # Copyright 2020 Canonical Ltd
244 #
245 # Licensed under the Apache License, Version 2.0 (the "License");
246@@ -16,196 +16,12 @@
247 # Authors:
248 # - edward.hope-morley@canonical.com
249
250-MAX_WAIT_ACTIVE=50
251-OPENRC=${1:-""}
252-
253-_delete_lb ()
254-{
255- openstack loadbalancer delete --cascade $1
256-}
257-
258-test_octavia_lb ()
259-{
260- ## OCTAVIA LOADBALANCER TEST
261- #
262- # This test requires project net, subnet, ext net and vm. These can be
263- # provided using env vars otherwise input is requested.
264- #
265- # export UA_OS_CHECKS_PROJECT_NET=<tenant network name or uuid>
266- # export UA_OS_CHECKS_PROJECT_SUBNET=<tenant subnet name or uuid>
267- # export UA_OS_CHECKS_EXT_NET=<external net name or uuid>
268- # export UA_OS_CHECKS_VM_UUID=<vm uuid>
269-
270- local rc=0
271- local net=$1
272- local subnet=$2
273- local ext_net=$3
274- local member_vm=$4
275- local test_tag=`uuidgen`
276- local lb_name=test-lb-${test_tag}
277-
278- exists="`juju status --format=json| jq '.applications| to_entries[]| select(.value.charm| test(\".+octavia.+\"))'`"
279- if [ -z "$exists" ]; then
280- echo "INFO: no octavia found - skipping test"
281- return 0
282- fi
283-
284- if [ -n "$UA_OS_CHECKS_PROJECT_NET" ]; then
285- net=$UA_OS_CHECKS_PROJECT_NET
286- else
287- read -p "Tenant network name to use for Octavia LB test: " net
288- fi
289- if [ -n "$UA_OS_CHECKS_PROJECT_SUBNET" ]; then
290- subnet=$UA_OS_CHECKS_PROJECT_SUBNET
291- else
292- read -p "Tenant subnet name to use for Octavia LB test: " subnet
293- fi
294- if [ -n "$UA_OS_CHECKS_EXT_NET" ]; then
295- ext_net=$UA_OS_CHECKS_EXT_NET
296- else
297- read -p "External net to use for Octavia LB test: " ext_net
298- fi
299- if [ -n "$UA_OS_CHECKS_VM_UUID" ]; then
300- member_vm=$UA_OS_CHECKS_VM_UUID
301- else
302- read -p "UUID of guest vm with something listening on port 80 (e.g. apache): " member_vm
303- fi
304-
305- lb_id=`openstack loadbalancer create --name $lb_name --vip-subnet-id $subnet -c id -f value`
306- wait_cycle=0
307- while true; do
308- ((wait_cycle++ < MAX_WAIT_ACTIVE)) || { _delete_lb $lb_id; return 1; }
309- status="`openstack loadbalancer show $lb_id -c provisioning_status -f value`"
310- [ "$status" = "ACTIVE" ] && break
311- [ "$status" = "ERROR" ] && { _delete_lb $lb_id; return 1; }
312- echo "Waiting for LB $lb_name (uuid=$lb_id) to be ACTIVE (current=$status)"
313- done
314- openstack loadbalancer listener create --name test-listener-${test_tag} --protocol HTTP --protocol-port 80 $lb_id
315- wait_cycle=0
316- while true; do
317- ((wait_cycle++ < MAX_WAIT_ACTIVE)) || { _delete_lb $lb_id; return 1; }
318- status="`openstack loadbalancer listener show test-listener-${test_tag} -c provisioning_status -f value`"
319- [ "$status" = "ACTIVE" ] && break
320- [ "$status" = "ERROR" ] && { _delete_lb $lb_id; return 1; }
321- echo "Waiting for Listener test-listener-${test_tag} to be ACTIVE (current=$status)"
322- done
323- openstack loadbalancer pool create --name test-pool-${test_tag} --lb-algorithm ROUND_ROBIN --listener test-listener-${test_tag} --protocol HTTP
324- wait_cycle=0
325- while true; do
326- ((wait_cycle++ < MAX_WAIT_ACTIVE)) || { _delete_lb $lb_id; return 1; }
327- status="`openstack loadbalancer pool show test-pool-${test_tag} -c provisioning_status -f value`"
328- [ "$status" = "ACTIVE" ] && break
329- [ "$status" = "ERROR" ] && { _delete_lb $lb_id; return 1; }
330- echo "Waiting for test-pool-${test_tag} to be ACTIVE (current=$status)"
331- done
332- openstack loadbalancer healthmonitor create --delay 5 --max-retries 4 --timeout 10 --type HTTP --url-path / test-pool-${test_tag}
333- openstack loadbalancer healthmonitor list
334- if [ -n "$member_vm" ]; then
335- netaddr=$(openstack port list --server $member_vm --network $net \
336- -c "Fixed IP Addresses" -f value | sed -r "s/.*ip_address(=|':\s+)'([[:digit:]\.]+)'.*/\2/g")
337- member_id=$(openstack loadbalancer member create --subnet-id $subnet \
338- --address $netaddr --protocol-port 80 --format value --column id test-pool-${test_tag})
339- wait_cycle=0
340- while true; do
341- ((wait_cycle++ < MAX_WAIT_ACTIVE)) || { _delete_lb $lb_id; return 1; }
342- status="`openstack loadbalancer member show -f value -c provisioning_status test-pool-${test_tag} $member_id`"
343- [ "$status" = ACTIVE ] && break
344- [ "$status" = "ERROR" ] && { _delete_lb $lb_id; return 1; }
345- echo "Waiting for member $member_vm ($member_id) to be ACTIVE (current=$status)"
346- done
347-
348- openstack loadbalancer member list test-pool-${test_tag}
349-
350- fip=`openstack floating ip create -f value -c floating_ip_address $ext_net`
351- lb_vip_port_id=$(openstack loadbalancer show -f value -c vip_port_id $lb_id)
352- openstack floating ip set --port $lb_vip_port_id $fip
353- # NOTE: floating ip may not be immediately available
354- retry_count=10
355- while ! ((rc)); do
356- nc -w 5 -vz $fip 80
357- rc=$?
358- if ((rc)) && ((retry_count>0)); then
359- rc=0
360- ((retry_count--))
361- sleep 1
362- else
363- break
364- fi
365- done
366- fi
367-
368- _delete_lb $lb_id
369-
370- # PASS
371- return $rc
372-}
373-
374-test_images_disk_format()
375-{
376- # Checks to see if Ceph backend is used in either Nova or Cinder and if it
377- # is, checks that all images in Glance have disk_format=raw.
378- # See the following KB article for information on why this is important:
379- # https://support.canonical.com/ua/s/article/openstack-boot-image-considerations
380-
381- local rc=0
382- local ftmp=`mktemp`
383-
384- exists="`juju status --format=json| jq '.applications| to_entries[]| select(.value.charm| test(\".+ceph-mon.+\"))'`"
385- if [ -z "$exists" ]; then
386- echo "INFO: no ceph-mon found - skipping test"
387- rm $ftmp
388- return 0
389- fi
390-
391- juju status ceph-mon --format=json > $ftmp
392- readarray -t clients<<<"`jq -r '.applications."ceph-mon".relations.client[]' $ftmp`"
393- if ((${#clients[@]})) && [ -n "${clients[0]}" ]; then
394- raw_required=false
395- for client in ${clients[@]}; do
396- if [[ $client =~ nova-compute.* ]] ||
397- [[ $client =~ cinder-ceph.* ]]; then
398- raw_required=true
399- break
400- fi
401- done
402- if $raw_required; then
403- openstack image list --long -c ID -c 'Disk Format' -f value > $ftmp
404- if ((`awk '{print $2}' $ftmp| sort -u| wc -l` > 1)); then
405-cat << EOF
406-WARNING: not all images in Glance have disk_format=raw
407-
408-Your environment is using Ceph as a backend for one or both of nova-compute
409-or cinder and as a result it is essential to use images with raw format in
410-order to avoid a large capacity and performance impact on your cloud and ceph
411-cluster. This format is also needed in order to benefit from Copy-on-Write
412-cloning of images in both Cinder and Nova.
413-
414-For more information on why this is important please see the following article:
415-
416- https://support.canonical.com/ua/s/article/openstack-boot-image-considerations
417-EOF
418- echo -e "\nImage format details:"
419- readarray -t formats<<<"`sort -k 2 $ftmp| awk '{print $2}'| uniq`"
420- for fmt in ${formats[@]}; do
421- awk "\$2==\"$fmt\" {print \$2}" $ftmp| sort| uniq -c
422- done
423- echo ""
424- rc=1
425- fi
426- else
427- echo "No hard requirement for raw images - skipping check"
428- fi
429- fi
430-
431- rm $ftmp
432- return $rc
433-}
434-
435+export OPENRC=${1:-""}
436
437 # Install dependencies
438 dpkg -s jq &>/dev/null || sudo apt install -y jq
439
440-## Run Tests
441+# Run Tests
442 cat << EOF
443 ================================================================================
444 Running extra Openstack checks on `date`.
445@@ -219,13 +35,12 @@ fi
446 . $OPENRC
447
448 # See function definitions for explanation.
449+CHECKS_DIR=`dirname $0`/extra-checks.d
450
451 echo -e "\nRunning Glance image format test"
452-test_images_disk_format && \
453- echo "Result: [PASS]" || echo "Result: [FAIL]"
454+$CHECKS_DIR/glance && echo "Result: [PASS]" || echo "Result: [FAIL]"
455
456 echo -e "\nRunning Octavia LoadBalancer test"
457-test_octavia_lb && \
458- echo "Result: [PASS]" || echo "Result: [FAIL]"
459+$CHECKS_DIR/octavia && echo "Result: [PASS]" || echo "Result: [FAIL]"
460
461 echo -e "\nDone."

Subscribers

People subscribed via source and target branches