[arvados] created: 2.5.0-62-gd9cb58fdf

git repository hosting git at public.arvados.org
Mon Jan 30 23:32:56 UTC 2023


        at  d9cb58fdfa203eee880dba91a239a1f0edf97422 (commit)


commit d9cb58fdfa203eee880dba91a239a1f0edf97422
Author: Brett Smith <brett.smith at curii.com>
Date:   Mon Jan 30 18:29:47 2023 -0500

    19897: Add tests for writing immutable mount objects
    
    I originally wrote these expecting to get them to return ENOTSUP as
    well. However, that doesn't happen now because of how the Operations
    class calls Directory.writable() and turns False into EPERM. I'm
    committing the tests since they're useful as-is, with a note that I'd
    like to convert them to ENOTSUP in the future.
    
    Arvados-DCO-1.1-Signed-off-by: Brett Smith <brett.smith at curii.com>

diff --git a/services/fuse/tests/test_mount.py b/services/fuse/tests/test_mount.py
index fa2b27f1f..f4e5138e2 100644
--- a/services/fuse/tests/test_mount.py
+++ b/services/fuse/tests/test_mount.py
@@ -1362,3 +1362,78 @@ class UnsupportedCreateTest(MountTestBase):
             with test_path.open('w'):
                 pass
         self.assertEqual(exc_check.exception.errno, errno.ENOTSUP)
+
+
+# FIXME: IMO, for consistency with the "create inside a project" case,
+# these operations should also return ENOTSUP instead of EPERM.
+# Right now they're returning EPERM because the clasess' writable() method
+# usually returns False, and the Operations class transforms that accordingly.
+# However, for cases where the mount will never be writable, I think ENOTSUP
+# is a clearer error: it lets the user know they can't fix the problem by
+# adding permissions in Arvados, etc.
+ at parameterized.parameterized_class([
+    {'root_class': fusedir.MagicDirectory,
+     'preset_dir': 'by_id',
+     'preset_file': 'README',
+     },
+
+    {'root_class': fusedir.SharedDirectory,
+     'root_kwargs': {
+         'exclude': run_test_server.fixture('users')['admin']['uuid'],
+     },
+     'preset_dir': 'Active User',
+     },
+
+    {'root_class': fusedir.TagDirectory,
+     'root_kwargs': {
+         'tag': run_test_server.fixture('links')['foo_collection_tag']['name'],
+     },
+     'preset_dir': run_test_server.fixture('collections')['foo_collection_in_aproject']['uuid'],
+     },
+
+    {'root_class': fusedir.TagsDirectory,
+     'preset_dir': run_test_server.fixture('links')['foo_collection_tag']['name'],
+     },
+])
+class UnsupportedOperationsTest(UnsupportedCreateTest):
+    preset_dir = None
+    preset_file = None
+
+    def test_create(self):
+        test_path = Path(self.mounttmp, 'test_create')
+        with self.assertRaises(OSError) as exc_check:
+            with test_path.open('w'):
+                pass
+        self.assertEqual(exc_check.exception.errno, errno.EPERM)
+
+    def test_mkdir(self):
+        test_path = Path(self.mounttmp, 'test_mkdir')
+        with self.assertRaises(OSError) as exc_check:
+            test_path.mkdir()
+        self.assertEqual(exc_check.exception.errno, errno.EPERM)
+
+    def test_rename(self):
+        src_name = self.preset_dir or self.preset_file
+        if src_name is None:
+            return
+        test_src = Path(self.mounttmp, src_name)
+        test_dst = test_src.with_name('test_dst')
+        with self.assertRaises(OSError) as exc_check:
+            test_src.rename(test_dst)
+        self.assertEqual(exc_check.exception.errno, errno.EPERM)
+
+    def test_rmdir(self):
+        if self.preset_dir is None:
+            return
+        test_path = Path(self.mounttmp, self.preset_dir)
+        with self.assertRaises(OSError) as exc_check:
+            test_path.rmdir()
+        self.assertEqual(exc_check.exception.errno, errno.EPERM)
+
+    def test_unlink(self):
+        if self.preset_file is None:
+            return
+        test_path = Path(self.mounttmp, self.preset_file)
+        with self.assertRaises(OSError) as exc_check:
+            test_path.unlink()
+        self.assertEqual(exc_check.exception.errno, errno.EPERM)

commit 60146acf7ae62f4d24f75d22c0bc19537d8d26b3
Author: Brett Smith <brett.smith at curii.com>
Date:   Mon Jan 30 18:24:12 2023 -0500

    19897: Return ENOTSUP when the user tries to make a file in a project
    
    Before this commit, the NotImplementedError is propagating up to
    catch_exceptions, which turns it into EIO. "I/O error" sounds like a
    problem with the underlying systems and stresses out users. "Operation
    not supported" should better communicate to the user that they're doing
    something unexpected and should double-check their work.
    
    Arvados-DCO-1.1-Signed-off-by: Brett Smith <brett.smith at curii.com>

diff --git a/services/fuse/arvados_fuse/__init__.py b/services/fuse/arvados_fuse/__init__.py
index 14dd7f3f8..31afcda8d 100644
--- a/services/fuse/arvados_fuse/__init__.py
+++ b/services/fuse/arvados_fuse/__init__.py
@@ -329,6 +329,8 @@ def catch_exceptions(orig_func):
             raise
         except EnvironmentError as e:
             raise llfuse.FUSEError(e.errno)
+        except NotImplementedError:
+            raise llfuse.FUSEError(errno.ENOTSUP)
         except arvados.errors.KeepWriteError as e:
             _logger.error("Keep write error: " + str(e))
             raise llfuse.FUSEError(errno.EIO)
diff --git a/services/fuse/tests/test_mount.py b/services/fuse/tests/test_mount.py
index a155acd14..fa2b27f1f 100644
--- a/services/fuse/tests/test_mount.py
+++ b/services/fuse/tests/test_mount.py
@@ -6,7 +6,9 @@ from __future__ import absolute_import
 from future.utils import viewitems
 from builtins import str
 from builtins import object
+from pathlib import Path
 from six import assertRegex
+import errno
 import json
 import llfuse
 import logging
@@ -20,6 +22,7 @@ import parameterized
 
 import arvados
 import arvados_fuse as fuse
+from arvados_fuse import fusedir
 from . import run_test_server
 
 from .integration_test import IntegrationTest
@@ -1331,3 +1334,31 @@ class ReadonlyCollectionTest(MountTestBase):
         self.make_mount(fuse.CollectionDirectory, collection_record=self.testcollection, enable_write=False)
 
         self.pool.apply(_readonlyCollectionTestHelper, (self.mounttmp,))
+
+
+ at parameterized.parameterized_class([
+    {'root_class': fusedir.ProjectDirectory, 'root_kwargs': {
+        'project_object': run_test_server.fixture('users')['admin'],
+    }},
+    {'root_class': fusedir.ProjectDirectory, 'root_kwargs': {
+        'project_object': run_test_server.fixture('groups')['public'],
+    }},
+])
+class UnsupportedCreateTest(MountTestBase):
+    root_class = None
+    root_kwargs = {}
+
+    def setUp(self):
+        super().setUp()
+        if 'prefs' in self.root_kwargs.get('project_object', ()):
+            self.root_kwargs['project_object']['prefs'] = {}
+        self.make_mount(self.root_class, **self.root_kwargs)
+        # Make sure the directory knows about its top-level ents.
+        os.listdir(self.mounttmp)
+
+    def test_create(self):
+        test_path = Path(self.mounttmp, 'test_create')
+        with self.assertRaises(OSError) as exc_check:
+            with test_path.open('w'):
+                pass
+        self.assertEqual(exc_check.exception.errno, errno.ENOTSUP)

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list