[ARVADOS] created: bf234475965f5908355435b246ac696c35d54556

git at public.curoverse.com git at public.curoverse.com
Mon Dec 14 14:04:47 EST 2015


        at  bf234475965f5908355435b246ac696c35d54556 (commit)


commit bf234475965f5908355435b246ac696c35d54556
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Fri Dec 11 14:49:01 2015 -0500

    7939: Move daemonize to _run_standalone() after llfuse.init(), preserving open
    file descriptors.  Add tests for various error conditions that can prevent
    successful mount.

diff --git a/services/fuse/arvados_fuse/command.py b/services/fuse/arvados_fuse/command.py
index 93bcd20..11935ad 100644
--- a/services/fuse/arvados_fuse/command.py
+++ b/services/fuse/arvados_fuse/command.py
@@ -4,6 +4,7 @@ import daemon
 import llfuse
 import logging
 import os
+import resource
 import signal
 import subprocess
 import sys
@@ -95,14 +96,6 @@ class Mount(object):
         if self.args.logfile:
             self.args.logfile = os.path.realpath(self.args.logfile)
 
-        # Daemonize as early as possible, so we don't accidentally close
-        # file descriptors we're using.
-        self.daemon_ctx = None
-        if not (self.args.exec_args or self.args.foreground):
-            os.chdir(self.args.mountpoint)
-            self.daemon_ctx = daemon.DaemonContext(working_directory='.')
-            self.daemon_ctx.open()
-
         try:
             self._setup_logging()
             self._setup_api()
@@ -141,8 +134,6 @@ class Mount(object):
         # Configure a log handler based on command-line switches.
         if self.args.logfile:
             log_handler = logging.FileHandler(self.args.logfile)
-        elif self.daemon_ctx:
-            log_handler = logging.NullHandler()
         else:
             log_handler = None
 
@@ -162,6 +153,7 @@ class Mount(object):
             keep_params={
                 "block_cache": arvados.keep.KeepBlockCache(self.args.file_cache)
             })
+        self.api.users().current().execute()
 
     def _setup_mount(self):
         self.operations = Operations(
@@ -189,6 +181,8 @@ class Mount(object):
 
         if self.args.collection is not None:
             # Set up the request handler with the collection at the root
+            # First check that the collection is readable
+            self.api.collections().get(uuid=self.args.collection).execute()
             self.args.mode = 'collection'
             dir_class = CollectionDirectory
             dir_args.append(self.args.collection)
@@ -326,6 +320,11 @@ From here, the following directories are available:
         try:
             llfuse.init(self.operations, self.args.mountpoint, self._fuse_options())
 
+            if not (self.args.exec_args or self.args.foreground):
+                self.daemon_ctx = daemon.DaemonContext(working_directory=os.path.dirname(self.args.mountpoint),
+                                                       files_preserve=range(3, resource.getrlimit(resource.RLIMIT_NOFILE)[1]))
+                self.daemon_ctx.open()
+
             # Subscribe to change events from API server
             self.operations.listen_for_events()
 
diff --git a/services/fuse/tests/test_command_args.py b/services/fuse/tests/test_command_args.py
index 19d56a9..8f040bc 100644
--- a/services/fuse/tests/test_command_args.py
+++ b/services/fuse/tests/test_command_args.py
@@ -187,3 +187,65 @@ class MountArgsTest(unittest.TestCase):
                         '--mount-tmp', name,
                         '--foreground', self.mntdir])
                     arvados_fuse.command.Mount(args)
+
+class MountErrorTest(unittest.TestCase):
+    def setUp(self):
+        self.mntdir = tempfile.mkdtemp()
+        run_test_server.run()
+        run_test_server.authorize_with("active")
+        self.logger = logging.getLogger("null")
+        self.logger.setLevel(logging.CRITICAL+1)
+
+    def tearDown(self):
+        if os.path.exists(self.mntdir):
+            # If the directory was not unmounted, this will raise an exception.
+            os.rmdir(self.mntdir)
+        run_test_server.reset()
+
+    def test_no_token(self):
+        del arvados.config._settings["ARVADOS_API_TOKEN"]
+        arvados.config._settings = {}
+        with self.assertRaises(SystemExit):
+            args = arvados_fuse.command.ArgumentParser().parse_args([self.mntdir])
+            arvados_fuse.command.Mount(args, logger=self.logger).run()
+
+    def test_no_host(self):
+        del arvados.config._settings["ARVADOS_API_HOST"]
+        with self.assertRaises(SystemExit):
+            args = arvados_fuse.command.ArgumentParser().parse_args([self.mntdir])
+            arvados_fuse.command.Mount(args, logger=self.logger).run()
+
+    def test_bogus_host(self):
+        arvados.config._settings["ARVADOS_API_HOST"] = "example.null"
+        with self.assertRaises(SystemExit):
+            args = arvados_fuse.command.ArgumentParser().parse_args([self.mntdir])
+            arvados_fuse.command.Mount(args, logger=self.logger).run()
+
+    def test_bogus_mount_dir(self):
+        # All FUSE errors in llfuse.init() are raised as RuntimeError
+        # An easy error to trigger is to supply a nonexistent mount point,
+        # so test that one.
+        #
+        # Other possible errors that also raise RuntimeError (but are much
+        # harder to test automatically because they depend on operating
+        # system configuration):
+        #
+        # The user doesn't have permission to use FUSE
+        # The user specified --allow-other but user_allow_other is not set
+        # in /etc/fuse.conf
+        os.rmdir(self.mntdir)
+        with self.assertRaises(SystemExit):
+            args = arvados_fuse.command.ArgumentParser().parse_args([self.mntdir])
+            arvados_fuse.command.Mount(args, logger=self.logger).run()
+
+    def test_unreadable_collection(self):
+        with self.assertRaises(SystemExit):
+            args = arvados_fuse.command.ArgumentParser().parse_args([
+                "--collection", "zzzzz-4zz18-zzzzzzzzzzzzzzz", self.mntdir])
+            arvados_fuse.command.Mount(args, logger=self.logger).run()
+
+    def test_unreadable_project(self):
+        with self.assertRaises(SystemExit):
+            args = arvados_fuse.command.ArgumentParser().parse_args([
+                "--project", "zzzzz-j7d0g-zzzzzzzzzzzzzzz", self.mntdir])
+            arvados_fuse.command.Mount(args, logger=self.logger).run()

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list