]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
test/librbd/test_notify.py: conditionally ignore some errors
authorIlya Dryomov <idryomov@gmail.com>
Sat, 5 Apr 2025 10:26:23 +0000 (12:26 +0200)
committerIlya Dryomov <idryomov@gmail.com>
Sat, 5 Apr 2025 17:20:08 +0000 (19:20 +0200)
In 2020, commit 01ff1530544c ("librbd: make all maintenance op
notifications async") introduced a backwards compatibility issue where
if exclusive lock is held by an older (octopus and below) client and
a maintenance op is proxied to it from a newer client, the newer client
interprets the notification for the in-place completion of the op as
the notification for the acceptance of an async request and expects
another notification for the completion of the op which never comes.
In 2021, this bug was discovered and test_notify.py was amended to
ignore it in commit 9c0b239d70cd ("qa/upgrade: conditionally disable
update_features tests").

However the two update_features tests that started hanging and got
disabled weren't the only ones to misbehave.  Rename, create_snap and
remove_snap tests were affected too but didn't hang or fail because
librbd also filtered certain errors codes like EEXIST and EINVAL.
Taking rename is an example:

1. a rename request is sent to from a newer client (N) to an octopus
   client (O)
2. O successfully renames the image and sends a completion notification
   with result = 0
3. N mistakes it for async request acceptance
4. after a timeout, N resends the rename request to O
5. O sees that an image already has that name (after step 2) and sends
   a completion notification with result = EEXIST
6. N interprets it as async request denial and bubbles up EEXIST,
   however right before returning control from Operations::rename()
   EEXIST is filtered and 0 is returned to the user

So back then rename, create_snap and remove_snap tests continued to
pass but started taking 30+ seconds instead of completing immediately.
In 2025 we did away with filtering error codes in commit 66508cdaa190
("librbd: stop filtering async request error codes") and these tests
started to fail.  Following the approach taken in commit 9c0b239d70cd
("qa/upgrade: conditionally disable update_features tests"), let's
ignore these failures based on the same environment variable.

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
src/test/librbd/test_notify.py

index 4e929d74fa46585aaec58242aa95b79e05e0bae1..03ecf1263a8cdd7e75d82119fd23280b4f84a84e 100755 (executable)
@@ -6,6 +6,7 @@ import time
 from rados import Rados
 from rbd import (RBD,
                  Image,
+                 ImageExists,
                  ImageNotFound,
                  RBD_FEATURE_EXCLUSIVE_LOCK,
                  RBD_FEATURE_LAYERING,
@@ -101,7 +102,13 @@ def slave(ioctx):
     print("detected master")
 
     print("rename")
-    RBD().rename(ioctx, CLONE_IMG_NAME, CLONE_IMG_RENAME);
+    try:
+        RBD().rename(ioctx, CLONE_IMG_NAME, CLONE_IMG_RENAME)
+    except ImageExists as e:
+        if 'RBD_DISABLE_UPDATE_FEATURES' in os.environ:
+            print("ignoring {}".format(e))
+        else:
+            raise
 
     with Image(ioctx, CLONE_IMG_RENAME) as image:
         print("flatten")
@@ -114,7 +121,13 @@ def slave(ioctx):
         assert(image.stat()['size'] == IMG_SIZE // 2)
 
         print("create_snap")
-        image.create_snap('snap1')
+        try:
+            image.create_snap('snap1')
+        except ImageExists as e:
+            if 'RBD_DISABLE_UPDATE_FEATURES' in os.environ:
+                print("ignoring {}".format(e))
+            else:
+                raise
         assert(not image.is_exclusive_lock_owner())
         assert(any(snap['name'] == 'snap1'
                    for snap in image.list_snaps()))
@@ -136,7 +149,13 @@ def slave(ioctx):
                    for snap in image.list_snaps()))
 
         print("remove_snap")
-        image.remove_snap('snap1-new')
+        try:
+            image.remove_snap('snap1-new')
+        except ImageNotFound as e:
+            if 'RBD_DISABLE_UPDATE_FEATURES' in os.environ:
+                print("ignoring {}".format(e))
+            else:
+                raise
         assert(not image.is_exclusive_lock_owner())
         assert(list(image.list_snaps()) == [])