A single nfs export typically contains multiple volumes. We were
handling this in the libvirt driver by:
1. On mount, we 'ensure' the mount is available, so we don't fail if
another instance already has it mounted.
2. On umount, we trap and ignore 'device is busy' so we don't fail if
another instance is already using it.
Unfortunately, while this works for serial mounts and unmounts, there
are multiple failure cases when volumes from the same export are
mounted and unmounted simultaneously. It causes an error if an
instance is stopped: as the qemu process is not actively using the
mountpoint it will not prevent an unmount for another volume on the
same mountpoint from succeeding. It will not be possible to restart
the instance, because its mountpoint will not be mounted.
To fix this, we create a singleton manager object, which tracks mounts
and umount requests per export, and calls the real mount/umount only
when required. It uses per-export locks to allow concurrency while
avoiding races. Because we now expect to know the state of the host at
all times, we no longer need to execute speculative mount/umount
commands.
As we track attachments (a mapping from volume to instance) rather
than volumes, we also gracefully support multi-attach.
This change implements this for nfs, but the solution is intended to
be extended to all LibvirtBaseFileSystemVolumeDrivers.
Closes-Bug: #1421550
Change-Id: I3155984d76df06371a6c45f633aa448168a96d64