19897: Return ENOTSUP when the user tries to make a file in a project
authorBrett Smith <brett.smith@curii.com>
Mon, 30 Jan 2023 23:24:12 +0000 (18:24 -0500)
committerBrett Smith <brett.smith@curii.com>
Mon, 30 Jan 2023 23:24:12 +0000 (18:24 -0500)
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@curii.com>

services/fuse/arvados_fuse/__init__.py
services/fuse/tests/test_mount.py

index 14dd7f3f85c229dd8c60b63766415957204ca850..31afcda8d12267970631372014706793ef95c9f3 100644 (file)
@@ -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)
index a155acd1484b1aa94e2ee75556dba3789bb47619..fa2b27f1f8c551cc7e09290b736306e132b11969 100644 (file)
@@ -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,))
+
+
+@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)