mount module

The mount API.

The high-level mount API is Mount and handles mount, umount, remount and checks for Back In Time. The low-level mount API is MountControl. The latter can be used to create own mounting services via subclassing it. See the following example.

Example

See this template to create your own mounting service by inheriting from MountControl. All you need to do is:

  • Add your settings in qt/settingsdialog.py.

  • Add settings in common/config.py.

  • Use the following template class MountDummy, rename and modify it to your needs.

  • Please use self.currentMountpoint as your local mountpoint.

  • Your class should inherit from mount.MountControl.

As real usage example see the two classes sshtools.SSH and encfstools.EncFS_mount.

This is the template:

class MountDummy(mount.MountControl):
    def __init__(self, *args, **kwargs):
        super(MountDummy, self).__init__(*args, **kwargs)

        self.all_kwargs = {}

        # First we need to map the settings.
        # If <arg> is in kwargs (e.g. if this class is called with
        # dummytools.Dummy(<arg> = <value>) this will map self.<arg> to
        # kwargs[<arg>]; else self.<arg> = <default> from config
        # e.g. self.setattrKwargs(<arg>, <default>, **kwargs)
        self.setattrKwargs(
            'user', self.config.get_dummy_user(self.profile_id), **kwargs)
        self.setattrKwargs(
            'host', self.config.get_dummy_host(self.profile_id), **kwargs)
        self.setattrKwargs(
            'port', self.config.get_dummy_port(self.profile_id), **kwargs)
        self.setattrKwargs(
            'password',
            self.config.password(self.parent, self.profile_id),
            store = False, **kwargs)

        self.setDefaultArgs()

        # If self.currentMountpoint is not the remote snapshot path
        # you can specify a subfolder of self.currentMountpoint for
        # the symlink
        self.symlink_subfolder = None

        self.mountproc = 'dummy'
        self.log_command = '%s: %s@%s' % (self.mode, self.user, self.host)

    def _mount(self):
        # Mount the service
        # Implement your mountprocess here.
        pass

    def _umount(self):
        # Umount the service
        # Implement your unmountprocess here.
        pass

    def preMountCheck(self, first_run = False):
        # Check what ever conditions must be given for the mount to be
        # done successful.
        # Raise MountException('Error description') if service can not mount
        # return True if everything is okay
        # all pre|post_[u]mount_check can also be used to prepare
        # things or clean up
        return True

    def postMountCheck(self):
        # Check if mount was successful
        # Raise MountException('Error description') if not
        return True

    def preUmountCheck(self):
        # Check if service is safe to umount
        # Raise MountException('Error description') if not
        return True

    def postUmountCheck(self):
        # Check if umount successful
        # Raise MountException('Error description') if not
        return True
class mount.Mount(cfg=None, profile_id=None, tmp_mount=False, parent=None)[source]

Bases: object

This is the high-level mount API. This will handle mount, umount, remount and checks on the low-level MountControl subclass backends for BackInTime.

If cfg is None this will load the default config. If profile_id is None it will use configfile.ConfigFileWithProfiles.currentProfile().

If the current profile uses Password-Cache and the Password-Cache is not running this will try to start it.

Parameters:
  • cfg (config.Config) – current config

  • profile_id (str) – profile ID that should be used

  • tmp_mount (bool) – if True mount to a temporary destination

  • parent (QWidget) – parent widget for QDialogs or None if there is no parent

mount(mode=None, check=True, **kwargs)[source]

High-level mount. Check if the selected mode need to be mounted, select the low-level backend and mount it.

Parameters:
  • mode (str) – mode to use. One of ‘local’, ‘ssh’, ‘local_encfs’ or ‘ssh_encfs’

  • check (bool) – if True run MountControl.preMountCheck() before mounting

  • **kwargs – keyword arguments paste to low-level MountControl subclass backend

Returns:

Hash ID used as mountpoint

Return type:

str

Raises:
preMountCheck(mode=None, first_run=False, **kwargs)[source]

High-level check. Run MountControl.preMountCheck() to check if all conditions for Mount.mount() are set.

Should be called with first_run = True to check if new settings are correct before saving them.

Parameters:
  • mode (str) – mode to use. One of ‘local’, ‘ssh’, ‘local_encfs’ or ‘ssh_encfs’

  • first_run (bool) – run intense checks that only need to run after changing settings but not every time before mounting

  • **kwargs – keyword arguments paste to low-level MountControl subclass backend

Returns:

True if all checks where okay

Return type:

bool

Raises:

exceptions.MountException – if a check failed

remount(new_profile_id, mode=None, hash_id=None, **kwargs)[source]

High-level remount. Unmount the old profile presented by hash_id and mount new profile new_profile_id with mode mode. If old and new mounts are the same just add new symlinks and keep the mount.

Args map to profiles:

new_profile_id          <= new profile
mode                    <= new profile
kwargs                  <= new profile
hash_id                 <= old profile
self.profile_id         <= old profile
Parameters:
  • new_profile_id (str) – Profile ID that should get mounted

  • mode (str) – mode to use for new mount. One of ‘local’, ‘ssh’, ‘local_encfs’ or ‘ssh_encfs’

  • hash_id (str) – Hash ID used as mountpoint on the old mount, that should get unmounted

  • **kwargs – keyword arguments paste to low-level MountControl subclass backend for the new mount

Returns:

Hash ID used as mountpoint

Return type:

str

Raises:
umount(hash_id=None)[source]

High-level unmount. Unmount the low-level backend. This will read unmount infos written next to the mountpoint identified by hash_id and unmount it.

Parameters:

hash_id (bool) – Hash ID used as mountpoint before that should get unmounted

Raises:

exceptions.MountException – if a check failed

class mount.MountControl(cfg=None, profile_id=None, hash_id=None, tmp_mount=False, parent=None, symlink=True, *args, **kwargs)[source]

Bases: object

This is the low-level mount API. This should be subclassed by backends.

Subclasses should have its own __init__ but must also call the inherited __init__. See module description (mount) for a detailed example.

You must overwrite methods:

You can overwrite methods:

These arguments (all of type str) must be defined in self namespace by subclassing __init__ method:

  • mountproc: process used to mount

  • log_command: shortened form of mount command used in logs

  • symlink_subfolder: mountpoint-subfolder which should be linked

Parameters:
  • cfg (config.Config) – current config

  • profile_id (str) – profile ID that should be used

  • hash_id (str) – crc32 hash used to identify identical mountpoints

  • tmp_mount (bool) – if True mount to a temporary destination

  • parent (QWidget) – parent widget for QDialogs or None if there is no parent

  • symlink (bool) – if True set symlink to mountpoint

  • mode (str) – one of local, local_encfs, ssh or ssh_encfs

  • hash_collision (int) – global value used to prevent hash collisions on mountpoints

_mount()[source]

Backend mount method. This must be overwritten in the backend which subclasses MountControl.

_umount()[source]

Unmount with fusermount -u for fuse based backends. This can be overwritten by backends which subclasses MountControl.

Raises:

exceptions.MountException – If unmount failed.

checkFuse()[source]

Check if command in self.mountproc is installed.

Raises:

exceptions.MountException – If either command is not available.

checkLocks(path, lockSuffix)[source]

Check if there are active locks ending with lockSuffix in path. If the process owning the lock doesn’t exist anymore this will remove the lock.

Parameters:
  • path (str) – full path to lock directory

  • lockSuffix (str) – last part of locks name

Returns:

True if there are active locks in path

Return type:

bool

compareRemount(old_hash_id)[source]

Compare mount arguments between current and old_hash_id. If they are identical we could reuse the mount and don’t need to remount.

Parameters:

old_hash_id (str) – Hash ID of the old mountpoint

Returns:

True if the old mountpoint and current are

identiacal

Return type:

bool

compareUmountInfo(umount_info=None)[source]

Compare current self.all_kwargs with those from file umount_info.

This should prevent hash collisions of two different mounts.

Parameters:

umount_info (str) – full path to <hash_id>/umount file

Returns:

True if self.all_kwargs and kwargs

read from umount_info file are identiacal

Return type:

bool

createMountStructure()[source]

Create folders that are necessary for mounting.

Folder structure in ~/.local/share/backintime/mnt/ (self.mount_root):

.
├── <pid>.lock              <=  mountprocess lock that will prevent
│                               different processes modifying
│                               mountpoints at one time
│
├── <hash_id>/              <=  ``self.hash_id_path`` will be
│   │                           shared by all profiles with the
│   │                           same mount settings
│   │
│   ├── mountpoint/         <=  ``self.currentMountpoint`` real
│   │                           mountpoint
│   │
│   ├── umount              <=  ``self.umount_info`` json file with
│   │                           all necessary args for unmount
│   │
│   └── locks/              <=  ``self.lock_path`` for each process
│                               you have a ``<pid>.lock`` file
│
├── <profile id>_<pid>/     <=  sym-link to the right path. return
│                               by config.snapshotsPath (can be
│                               ../mnt/<hash_id>/mount_point for ssh
│                               or ../mnt/<hash_id>/<HOST>/<SHARE>
│                               for fusesmb ...)
│
└── tmp_<profile id>_<pid>/ <=  sym-link for testing mountpoints
                                in settingsdialog
hash(s)[source]

Create a CRC32 hash of string s.

Parameters:

s (str) – string that should be hashed

Returns:

hash of string s

Return type:

str

hashIdPath(hash_id=None)[source]

Get path ~/.local/share/backintime/mnt/<hash_id>.

Parameters:

hash_id (str) – Unique identifier for a mountpoint. If None use self.hash_id

Returns:

full path to <hash_id>

Return type:

str

lockPath(hash_id=None)[source]

Get path ~/.local/share/backintime/mnt/<hash_id>/locks.

Parameters:

hash_id (str) – Unique identifier for a mountpoint

Returns:

full path to <hash_id>/locks`

Return type:

str

mount(check=True)[source]

Low-level mount. Set mountprocess lock and prepare mount, run checks and than call _mount() for the subclassed backend. Finally set mount lock and symlink and release mountprocess lock.

Parameters:

check (bool) – if True run preMountCheck() before mounting

Returns:

Hash ID used as mountpoint

Return type:

str

Raises:
mountLockAquire()[source]

Create a lock for a mountpoint to prevent unmounting as long as this process is still running.

mountLockCheck()[source]

Check for locks on the current mountpoint.

Returns:

True if there are any locks

Return type:

bool

mountLockRelease()[source]

Remove mountpoint lock for this process.

mountProcessLockAcquire(timeout=60)[source]

Create a short term lock only for blocking other processes changing mounts at the same time.

Parameters:

timeout (int) – wait timeout seconds before fail acquiring the lock

Raises:

exceptions.MountException – if timed out

mountProcessLockRelease()[source]

Remove mountprocess lock.

mounted()[source]

Check if the mountpoint is already mounted.

Returns:

True if mountpoint is mounted

Return type:

bool

Raises:

exceptions.MountException – if mountpoint is not mounted but also not empty

mountpoint(hash_id=None)[source]

Get path ~/.local/share/backintime/mnt/<hash_id>/mountpoint.

Parameters:

hash_id (str) – Unique identifier for a mountpoint

Returns:

full path to <hash_id>/mountpoint

Return type:

str

postMountCheck()[source]

Check if the mount was successful. This can be overwritten in backends which subclasses MountControl.

Returns:

True if all checks where okay

Return type:

bool

Raises:

exceptions.MountException – if backend wasn’t mount successful

Note

This can also be used to clean up after running _mount()

postUmountCheck()[source]

Check if unmount was successful. This can be overwritten in backends which subclasses MountControl.

Returns:

True if all checks where okay

Return type:

bool

Raises:

exceptions.MountException – if backend wasn’t unmounted successful

Note

This can also be used to clean up after running _umount()

preMountCheck(first_run=False)[source]

Check what ever conditions must be given for the mount to be done successful. This can be overwritten in backends which subclasses MountControl.

Returns:

True if all checks where okay

Return type:

bool

Raises:

exceptions.MountException – if backend can not mount

Note

This can also be used to prepare things before running _mount()

preUmountCheck()[source]

Check if backend is safe to umount. This can be overwritten in backends which subclasses MountControl.

Returns:

True if all checks where okay

Return type:

bool

Raises:

exceptions.MountException – if backend can not umount

Note

This can also be used to prepare things before running _umount()

readUmountInfo(umount_info=None)[source]

Read keyword arguments from file umount_info.

Parameters:

umount_info (str) – full path to <hash_id>/umount file. If None current <hash_id>/umount file will be used

Returns:

previously written self.all_kwargs

Return type:

dict

Remove symlink ~/.local/share/backintime/mnt/<profile id>_<pid>

Parameters:
  • profile_id (str) – Profile ID for the symlink

  • tmp_mount (bool) – Symlink is a temporary link for testing new settings

setDefaultArgs()[source]

Set some arguments which are necessary for all backends. self.all_kwargs need to be filled through setattrKwargs() before calling this.

If self.symlink is True set symlink ~/.local/share/backintime/mnt/<profile id>_<pid>. Target will be either the mountpoint or a subfolder of the mountpoint if self.symlink_subfolder is set.

Parameters:
  • profile_id (str) – Profile ID that should be linked. If None use self.profile_id

  • hash_id (str) – Hash ID of mountpoint where this sysmlink should point to. If None use self.hash_id

  • tmp_mount (bool) – Set a temporary symlink just for testing new settings

setattrKwargs(arg, default, store=True, **kwargs)[source]

Set attribute arg in local namespace (self.arg). Also collect all args in self.all_kwargs which will be hashed later and used as mountpoint name and also be written as unmount_info.

Parameters:
  • arg (str) – argument name

  • default – default value used if arg is not in kwargs

  • store (bool) – if True add arg to self.all_kwargs

  • **kwargs – arguments given on backend constructor

umount()[source]

Low-level umount. Set mountprocess lock, run umount checks and call _umount() for the subclassed backend. Finally release mount lock, remove symlink and release mountprocess lock.

Raises:

exceptions.MountException – if a check failed

umountInfoPath(hash_id=None)[source]

Get path ~/.local/share/backintime/mnt/<hash_id>/umount.

Parameters:

hash_id (str) – Unique identifier for a mountpoint

Returns:

full path to <hash_id>/umount`

Return type:

str

writeUmountInfo()[source]

Write content of self.all_kwargs to file ~/.local/share/backintime/mnt/<hash_id>/umount. This will be used to unmount the filesystem later.