]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
qa: add helpful exceptions for attr changes
authorPatrick Donnelly <pdonnell@ibm.com>
Tue, 31 Dec 2024 17:57:53 +0000 (12:57 -0500)
committerPatrick Donnelly <pdonnell@ibm.com>
Fri, 28 Feb 2025 00:55:45 +0000 (19:55 -0500)
It's not possible to extract the error message from stderr by the caller.

Signed-off-by: Patrick Donnelly <pdonnell@ibm.com>
qa/tasks/cephfs/mount.py

index 52362d853dcfb6b3b87971e1ebc3b0527fb7f393..ddf6c2657a0334676872fb70383857abafb8d139 100644 (file)
@@ -23,6 +23,14 @@ log = logging.getLogger(__name__)
 
 UMOUNT_TIMEOUT = 300
 
+class NoSuchAttributeError(SystemError):
+    pass
+class InvalidArgumentError(SystemError):
+    pass
+class DirectoryNotEmptyError(SystemError):
+    pass
+class OperationNotPermittedError(SystemError):
+    pass
 
 class CephFSMountBase(object):
     def __init__(self, ctx, test_dir, client_id, client_remote,
@@ -1564,7 +1572,23 @@ class CephFSMountBase(object):
             # gives you [''] instead of []
             return []
 
-    def removexattr(self, path, key, **kwargs):
+    def _convert_attr_error(self, p, e):
+        stderr = p.stderr.getvalue()
+        log.error("attr: %s", stderr)
+        if "No such attribute" in stderr:
+            raise NoSuchAttributeError()
+        elif "Invalid" in stderr:
+            raise InvalidArgumentError()
+        elif "Permission" in stderr:
+            raise PermissionError()
+        elif "Directory not empty" in stderr:
+            raise DirectoryNotEmptyError()
+        elif "Operation not permitted" in stderr:
+            raise OperationNotPermittedError()
+        else:
+            raise e
+
+    def removexattr(self, path, key, helpfulexception=False, **kwargs):
         """
         Wrap setfattr removal.
 
@@ -1576,9 +1600,21 @@ class CephFSMountBase(object):
         if kwargs.pop('sudo', False):
             kwargs['args'].insert(0, 'sudo')
             kwargs['omit_sudo'] = False
-        self.run_shell(**kwargs)
+        wait = kwargs.setdefault('wait', True)
+        if wait:
+            kwargs['wait'] = False
+        p = self.run_shell(**kwargs)
+        try:
+            if wait:
+                p.wait()
+        except CommandFailedError as e:
+            if helpfulexception:
+                return self._convert_attr_error(p, e)
+            else:
+                raise
+        return p
 
-    def setfattr(self, path, key, val, **kwargs):
+    def setfattr(self, path, key, val, helpfulexception=False, **kwargs):
         """
         Wrap setfattr.
 
@@ -1591,9 +1627,22 @@ class CephFSMountBase(object):
         if kwargs.pop('sudo', False):
             kwargs['args'].insert(0, 'sudo')
             kwargs['omit_sudo'] = False
-        return self.run_shell(**kwargs)
+        wait = kwargs.setdefault('wait', True)
+        if wait:
+            kwargs['wait'] = False
+        p = self.run_shell(**kwargs)
+        try:
+            if wait:
+                p.wait()
+        except CommandFailedError as e:
+            if helpfulexception:
+                return self._convert_attr_error(p, e)
+            else:
+                raise
+        return p
+
 
-    def getfattr(self, path, attr, **kwargs):
+    def getfattr(self, path, attr, helpfulexception=False, **kwargs):
         """
         Wrap getfattr: return the values of a named xattr on one file, or
         None if the attribute is not found.
@@ -1604,16 +1653,23 @@ class CephFSMountBase(object):
         if kwargs.pop('sudo', False):
             kwargs['args'].insert(0, 'sudo')
             kwargs['omit_sudo'] = False
-        kwargs['wait'] = False
+        wait = kwargs.setdefault('wait', True)
+        if wait:
+            kwargs['wait'] = False
         p = self.run_shell(**kwargs)
         try:
-            p.wait()
+            if wait:
+                p.wait()
+            else:
+                return p
         except CommandFailedError as e:
-            if e.exitstatus == 1 and "No such attribute" in p.stderr.getvalue():
-                return None
+            if helpfulexception:
+                return self._convert_attr_error(p, e)
             else:
-                raise
-
+                if e.exitstatus == 1 and "No such attribute" in p.stderr.getvalue():
+                    return None
+                else:
+                    raise
         return str(p.stdout.getvalue())
 
     def df(self):