Skip to content

Commit 3fb9323

Browse files
committed
General code improvements, better detection of cinder-backup missing
Signed-off-by: Matthias Büchse <[email protected]>
1 parent ee5d30b commit 3fb9323

File tree

1 file changed

+66
-32
lines changed

1 file changed

+66
-32
lines changed

Tests/iaas/volume-backup/volume-backup-tester.py

Lines changed: 66 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"""
1515

1616
import argparse
17+
from functools import partial
1718
import getpass
1819
import logging
1920
import os
@@ -28,25 +29,66 @@
2829
DEFAULT_PREFIX = "scs-test-"
2930

3031

31-
def wait_for_resource(
32+
def check_resources(
33+
get_func: typing.Callable[[], [openstack.resource.Resource]],
34+
prefix: str,
35+
) -> None:
36+
remaining = [b for b in get_func() if b.name.startswith(prefix)]
37+
if remaining:
38+
raise RuntimeError(f"unexpected resources: {remaining}")
39+
40+
41+
def check_resource(
3242
get_func: typing.Callable[[str], openstack.resource.Resource],
3343
resource_id: str,
3444
expected_status=("available", ),
45+
) -> None:
46+
resource = get_func(resource_id)
47+
if resource is None:
48+
raise RuntimeError(f"resource {resource_id} not found")
49+
if resource.status not in expected_status:
50+
raise RuntimeError(
51+
f"Expect resource {resource_id} in "
52+
f"to be in status {expected_status} (current: {resource.status})"
53+
)
54+
55+
56+
class TimeoutError(Exception):
57+
pass
58+
59+
60+
def retry(
61+
func: callable,
3562
timeouts=(2, 3, 5, 10, 15, 25, 50),
3663
) -> None:
3764
seconds_waited = 0
3865
timeout_iter = iter(timeouts)
39-
resource = get_func(resource_id)
40-
while resource is None or resource.status not in expected_status:
41-
wait_delay = next(timeout_iter, None)
42-
if wait_delay is None:
43-
raise RuntimeError(
44-
f"Timed out after {seconds_waited} s: waiting for resource {resource_id} "
45-
f"to be in status {expected_status} (current: {resource and resource.status})"
46-
)
47-
time.sleep(wait_delay)
48-
seconds_waited += wait_delay
49-
resource = get_func(resource_id)
66+
while True:
67+
try:
68+
func()
69+
except Exception as e:
70+
wait_delay = next(timeout_iter, None)
71+
if wait_delay is None:
72+
raise TimeoutError(f"Timed out after {seconds_waited} s: {e!s}")
73+
time.sleep(wait_delay)
74+
seconds_waited += wait_delay
75+
else:
76+
break
77+
78+
79+
def wait_for_resource(
80+
get_func: typing.Callable[[str], openstack.resource.Resource],
81+
resource_id: str,
82+
expected_status=("available", ),
83+
) -> None:
84+
retry(partial(check_resource, get_func, resource_id, expected_status))
85+
86+
87+
def wait_for_resources(
88+
get_func: typing.Callable[[], [openstack.resource.Resource]],
89+
prefix: str,
90+
):
91+
retry(partial(check_resources, get_func, prefix))
5092

5193

5294
def test_backup(conn: openstack.connection.Connection, prefix=DEFAULT_PREFIX) -> None:
@@ -131,33 +173,25 @@ def cleanup(conn: openstack.connection.Connection, prefix=DEFAULT_PREFIX) -> boo
131173
expected_status=("available", "error"),
132174
)
133175
logging.info(f"↳ deleting volume backup '{backup.id}' ...")
134-
conn.block_storage.delete_backup(backup.id)
135-
except openstack.exceptions.ResourceNotFound:
136-
# if the resource has vanished on its own in the meantime ignore it
137-
continue
176+
conn.block_storage.delete_backup(backup.id, ignore_missing=False)
138177
except Exception as e:
178+
if isinstance(e, openstack.exceptions.ResourceNotFound):
179+
# if the resource has vanished on its own in the meantime ignore it
180+
# however, ResourceNotFound will also be thrown if the service 'cinder-backup' is missing
181+
if 'cinder-backup' in str(e):
182+
raise
183+
continue
139184
# Most common exception would be a timeout in wait_for_resource.
140185
# We do not need to increment cleanup_issues here since
141186
# any remaining ones will be caught in the next loop down below anyway.
142-
logging.debug("traceback", exc_info=True)
143187
logging.warning(str(e))
144188

145189
# wait for all backups to be cleaned up before attempting to remove volumes
146-
seconds_waited = 0
147-
while len(
148-
# list of all backups whose name starts with the prefix
149-
[b for b in conn.block_storage.backups() if b.name.startswith(prefix)]
150-
) > 0:
151-
time.sleep(1.0)
152-
seconds_waited += 1
153-
if seconds_waited >= 100:
154-
cleanup_issues += 1
155-
logging.warning(
156-
f"Timeout reached while waiting for all backups with prefix "
157-
f"'{prefix}' to finish deletion during cleanup after "
158-
f"{seconds_waited} seconds"
159-
)
160-
break
190+
try:
191+
wait_for_resources(conn.block_storage.backups, prefix)
192+
except TimeoutError as e:
193+
cleanup_issues += 1
194+
logging.warning(str(e))
161195

162196
volumes = conn.block_storage.volumes()
163197
for volume in volumes:

0 commit comments

Comments
 (0)