borg umount, fixes #1855

this refactors umount code we already used for the testsuite into the platform module's namespace.

also, it exposes that functionality via the cli api, so users can use it via "borg umount <mountpoint>",
which is more consistent than using borg to mount and fusermount -u (or umount) to un-mount.
This commit is contained in:
Thomas Waldmann 2016-11-17 20:16:28 +01:00
parent d871efc04a
commit e17fe2b295
9 changed files with 82 additions and 12 deletions

View File

@ -34,6 +34,7 @@ from .key import key_creator, RepoKey, PassphraseKey
from .keymanager import KeyManager
from .archive import backup_io, BackupOSError, Archive, ArchiveChecker, CHUNKER_PARAMS, is_special
from .remote import RepositoryServer, RemoteRepository, cache_if_remote
from .platform import umount
has_lchflags = hasattr(os, 'lchflags')
@ -539,6 +540,10 @@ class Archiver:
self.exit_code = EXIT_ERROR
return self.exit_code
def do_umount(self, args):
"""un-mount the FUSE filesystem"""
return umount(args.mountpoint)
@with_repository()
def do_list(self, args, repository, manifest, key):
"""List archive or repository contents"""
@ -1476,6 +1481,21 @@ class Archiver:
subparser.add_argument('-o', dest='options', type=str,
help='Extra mount options')
umount_epilog = textwrap.dedent("""
This command un-mounts a FUSE filesystem that was mounted with ``borg mount``.
This is a convenience wrapper that just calls the platform-specific shell
command - usually this is either umount or fusermount -u.
""")
subparser = subparsers.add_parser('umount', parents=[common_parser],
description=self.do_umount.__doc__,
epilog=umount_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
help='umount repository')
subparser.set_defaults(func=self.do_umount)
subparser.add_argument('mountpoint', metavar='MOUNTPOINT', type=str,
help='mountpoint of the filesystem to umount')
info_epilog = textwrap.dedent("""
This command displays some detailed information about the specified archive.

View File

@ -88,7 +88,7 @@ def check_extension_modules():
raise ExtensionModuleError
if crypto.API_VERSION != 2:
raise ExtensionModuleError
if platform.API_VERSION != 2:
if platform.API_VERSION != 3:
raise ExtensionModuleError

View File

@ -1,5 +1,6 @@
import errno
import os
import subprocess
import sys
@ -17,14 +18,19 @@ def sync_dir(path):
os.close(fd)
# most POSIX platforms (but not Linux), see also borg 1.1 platform.base
def umount(mountpoint):
return subprocess.call(['umount', mountpoint])
if sys.platform.startswith('linux'): # pragma: linux only
from .platform_linux import acl_get, acl_set, API_VERSION
from .platform_linux import acl_get, acl_set, umount, API_VERSION
elif sys.platform.startswith('freebsd'): # pragma: freebsd only
from .platform_freebsd import acl_get, acl_set, API_VERSION
elif sys.platform == 'darwin': # pragma: darwin only
from .platform_darwin import acl_get, acl_set, API_VERSION
else: # pragma: unknown platform only
API_VERSION = 2
API_VERSION = 3
def acl_get(path, item, st, numeric_owner=False):
pass

View File

@ -1,7 +1,7 @@
import os
from .helpers import user2uid, group2gid, safe_decode, safe_encode
API_VERSION = 2
API_VERSION = 3
cdef extern from "sys/acl.h":
ctypedef struct _acl_t:

View File

@ -1,7 +1,7 @@
import os
from .helpers import posix_acl_use_stored_uid_gid, safe_encode, safe_decode
API_VERSION = 2
API_VERSION = 3
cdef extern from "errno.h":
int errno

View File

@ -1,9 +1,10 @@
import os
import re
import subprocess
from stat import S_ISLNK
from .helpers import posix_acl_use_stored_uid_gid, user2uid, group2gid, safe_decode, safe_encode
API_VERSION = 2
API_VERSION = 3
cdef extern from "sys/types.h":
int ACL_TYPE_ACCESS
@ -141,3 +142,7 @@ def acl_set(path, item, numeric_owner=False):
acl_set_file(p, ACL_TYPE_DEFAULT, default_acl)
finally:
acl_free(default_acl)
def umount(mountpoint):
return subprocess.call(['fusermount', '-u', mountpoint])

View File

@ -9,6 +9,7 @@ import time
import unittest
from ..xattr import get_all
from ..logger import setup_logging
from ..platform import umount
try:
import llfuse
@ -110,11 +111,7 @@ class BaseTestCase(unittest.TestCase):
self.cmd(*args, fork=True)
self.wait_for_mount(mountpoint)
yield
if sys.platform.startswith('linux'):
cmd = 'fusermount -u %s' % mountpoint
else:
cmd = 'umount %s' % mountpoint
os.system(cmd)
umount(mountpoint)
os.rmdir(mountpoint)
# Give the daemon some time to exit
time.sleep(.2)

View File

@ -545,6 +545,8 @@ Examples
.. include:: usage/mount.rst.inc
.. include:: usage/umount.rst.inc
Examples
~~~~~~~~
::
@ -552,7 +554,7 @@ Examples
$ borg mount /path/to/repo::root-2016-02-15 /tmp/mymountpoint
$ ls /tmp/mymountpoint
bin boot etc home lib lib64 lost+found media mnt opt root sbin srv tmp usr var
$ fusermount -u /tmp/mymountpoint
$ borg umount /tmp/mymountpoint
.. include:: usage/key_export.rst.inc

40
docs/usage/umount.rst.inc Normal file
View File

@ -0,0 +1,40 @@
.. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!
.. _borg_umount:
borg umount
-----------
::
usage: borg umount [-h] [--critical] [--error] [--warning] [--info] [--debug]
[--lock-wait N] [--show-rc] [--no-files-cache] [--umask M]
[--remote-path PATH]
MOUNTPOINT
un-mount the FUSE filesystem
positional arguments:
MOUNTPOINT mountpoint of the filesystem to umount
optional arguments:
-h, --help show this help message and exit
--critical work on log level CRITICAL
--error work on log level ERROR
--warning work on log level WARNING (default)
--info, -v, --verbose
work on log level INFO
--debug work on log level DEBUG
--lock-wait N wait for the lock, but max. N seconds (default: 1).
--show-rc show/log the return code (rc)
--no-files-cache do not load/update the file metadata cache used to
detect unchanged files
--umask M set umask to M (local and remote, default: 0077)
--remote-path PATH set remote path to executable (default: "borg")
Description
~~~~~~~~~~~
This command un-mounts a FUSE filesystem that was mounted with ``borg mount``.
This is a convenience wrapper that just calls the platform-specific shell
command - usually this is either umount or fusermount -u.