1
0
mirror of https://github.com/projectatomic/atomic.git synced 2026-02-07 06:44:52 +01:00

Merge pull request #85 from willmtemple/mount-overlay-backend

OverlayFS DockerMount backend for atomic mount command.
This commit is contained in:
Daniel J Walsh
2015-07-10 15:17:14 -04:00
4 changed files with 88 additions and 12 deletions

View File

@@ -242,12 +242,21 @@ class DockerMount(Mount):
''.format(identifier))
@staticmethod
def _no_gd_api(cid):
def _no_gd_api_dm(cid):
# TODO: Deprecated
desc_file = os.path.join('/var/lib/docker/devicemapper/metadata', cid)
desc = json.loads(open(desc_file).read())
return desc['device_id'], desc['size']
@staticmethod
def _no_gd_api_overlay(cid):
# TODO: Deprecated
prefix = os.path.join('/var/lib/docker/overlay/', cid)
ld_metafile = open(os.path.join(prefix, 'lower-id'))
ld_loc = os.path.join('/var/lib/docker/overlay/', ld_metafile.read())
return (os.path.join(ld_loc, 'root'), os.path.join(prefix, 'upper'),
os.path.join(prefix, 'work'))
def mount(self, identifier, options=[]):
"""
Mounts a container or image referred to by identifier to
@@ -305,13 +314,13 @@ class DockerMount(Mount):
dm_dev_name, dm_dev_id, dm_dev_size = '', '', ''
dm_pool = info['DriverStatus'][0][1]
if 'GraphDriver' in cinfo:
try:
dm_dev_name = cinfo['GraphDriver']['Data']['DeviceName']
dm_dev_id = cinfo['GraphDriver']['Data']['DeviceId']
dm_dev_size = cinfo['GraphDriver']['Data']['DeviceSize']
else:
except:
# TODO: deprecated when GraphDriver patch makes it upstream
dm_dev_id, dm_dev_size = DockerMount._no_gd_api(cid)
dm_dev_id, dm_dev_size = DockerMount._no_gd_api_dm(cid)
dm_dev_name = dm_pool.replace('pool', cid)
dm_dev_path = os.path.join('/dev/mapper', dm_dev_name)
@@ -338,6 +347,42 @@ class DockerMount(Mount):
self._cleanup_container(cinfo)
raise de
def _mount_overlay(self, identifier, options):
"""
OverlayFS mount backend.
"""
if os.geteuid() != 0:
raise MountError('Insufficient privileges to mount device.')
if self.live:
raise MountError('The OverlayFS backend does not support live '
'mounts.')
elif 'rw' in options:
raise MountError('The OverlayFS backend does not support '
'writeable mounts.')
cid = self._identifier_as_cid(identifier)
cinfo = self.client.inspect_container(cid)
ld, ud, wd = '', '', ''
try:
ld = cinfo['GraphDriver']['Data']['lowerDir']
ud = cinfo['GraphDriver']['Data']['upperDir']
wd = cinfo['GraphDriver']['Data']['workDir']
except:
ld, ud, wd = DockerMount._no_gd_api_overlay(cid)
options += ['ro', 'lowerdir=' + ld, 'upperdir=' + ud, 'workdir=' + wd]
optstring = ','.join(options)
cmd = ['mount', '-t', 'overlay', '-o', optstring, 'overlay',
self.mountpoint]
status = util.subp(cmd)
if status.return_code != 0:
self._cleanup_container(cinfo)
raise MountError('Failed to mount OverlayFS device.\n' +
status.stderr)
def _cleanup_container(self, cinfo):
"""
Remove a container and clean up its image if necessary.
@@ -398,3 +443,30 @@ class DockerMount(Mount):
Mount._remove_thin_device(dev_name)
self._cleanup_container(cinfo)
def _get_overlay_mount_cid(self):
"""
Returns the cid of the container mounted at mountpoint.
"""
cmd = ['findmnt', '-o', 'OPTIONS', '-n', self.mountpoint]
r = util.subp(cmd)
if r.return_code != 0:
raise MountError('No devices mounted at that location.')
optstring = r.stdout.strip().split('\n')[-1]
upperdir = [o.replace('upperdir=', '') for o in optstring.split(',')
if o.startswith('upperdir=')][0]
cdir = upperdir.rsplit('/', 1)[0]
if not cdir.startswith('/var/lib/docker/overlay/'):
raise MountError('The device mounted at that location is not a '
'docker container.')
return cdir.replace('/var/lib/docker/overlay/', '')
def _unmount_overlay(self):
"""
OverlayFS unmount backend.
"""
if Mount.get_dev_at_mountpoint(self.mountpoint) != 'overlay':
raise MountError('Device mounted at {} is not an atomic mount.')
cid = self._get_overlay_mount_cid()
Mount.unmount_path(self.mountpoint)
self._cleanup_container(self.client.inspect_container(cid))

View File

@@ -19,23 +19,27 @@ If the given UUID or NAME is a container, and **--live** is not set, then
temporary image and spawning a temporary container from that image. If UUID or
REPO refers to an image, then *atomic mount* will simply create a temporary
container from the given image. All temporary artifacts are cleaned upon
*atomic unmount*.
*atomic unmount*. Atomic mount is *only* supported on the devicemapper and
overlayfs docker storage backends.
# OPTIONS
**-o|--options** *OPTIONS*
Specify options to be passed to *mount*. All options accepted by the 'mount'
command are valid. The default mount options (if the **--live** flag is unset)
are: 'ro,nodev,nosuid'. If the **-o** flag is specified, then no default
options are assumed. Use of the 'rw' flag is discouraged, as writes into the
atomic temporary containers are never preserved. Use of this option conflicts
with **--live**, as live containers have predetermined, immutable mount
options.
command are valid. The default mount options for the devicemapper backend (if
the **--live** flag is unset) are: 'ro,nodev,nosuid'. If the **-o** flag is
specified, then no default options are assumed. Use of the 'rw' flag is
discouraged, as writes into the atomic temporary containers are never
preserved. Use of this option conflicts with **--live**, as live containers
have predetermined, immutable mount options. The OverlayFS driver has, by
default, only the 'ro' option set, and the 'rw' option is illegal and will
cause the program to terminate.
**--live**
Mount a container live, writable, and synchronized. This option allows the user
to modify the container's contents as it runs or update the container's
software without rebuilding the container. If live mode is used, no mount
options may be provided.
options may be provided. Live mode is *not* supported on the OverlayFS docker
storage driver.
# HISTORY
June 2015, Originally compiled by William Temple (wtemple at redhat dot com)

0
tests/integration/test_mount.sh Normal file → Executable file
View File

0
tests/integration/test_pass.sh Normal file → Executable file
View File