Add NFS/GlusterFS support to brick library

Refactor NFS driver to use the brick library to perform mounts
rather than duplicating the mount code. Some of the NFS unit
test code was rewritten to test the brick implementation because
the old mount code was moved.

The Gluster driver was slightly affected in the refactoring, but
does not yet use brick to perform attaches.

bug 1214748

Change-Id: Ib29f83fabe407f9591191e9fd19e6306ca9960cf
This commit is contained in:
Ben Swartzlander 2013-08-27 21:43:20 -07:00
parent 4daffc63e7
commit 7523489e85
9 changed files with 353 additions and 177 deletions

View File

@ -26,6 +26,7 @@ from cinder.brick import executor
from cinder.brick.initiator import host_driver
from cinder.brick.initiator import linuxfc
from cinder.brick.initiator import linuxscsi
from cinder.brick.remotefs import remotefs
from cinder.openstack.common.gettextutils import _
from cinder.openstack.common import lockutils
from cinder.openstack.common import log as logging
@ -104,6 +105,11 @@ class InitiatorConnector(executor.Executor):
return AoEConnector(execute=execute,
driver=driver,
root_helper=root_helper)
elif protocol == "NFS" or protocol == "GLUSTERFS":
return RemoteFsConnector(mount_type=protocol.lower(),
execute=execute,
driver=driver,
root_helper=root_helper)
else:
msg = (_("Invalid InitiatorConnector protocol "
"specified %(protocol)s") %
@ -761,3 +767,45 @@ class AoEConnector(InitiatorConnector):
check_exit_code=0)
LOG.debug(_('aoe-flush %(dev)s: stdout=%(out)s stderr%(err)s') %
{'dev': aoe_device, 'out': out, 'err': err})
class RemoteFsConnector(InitiatorConnector):
"""Connector class to attach/detach NFS and GlusterFS volumes."""
def __init__(self, mount_type, root_helper, driver=None,
execute=putils.execute, *args, **kwargs):
self._remotefsclient = remotefs.RemoteFsClient(mount_type,
execute, root_helper)
super(RemoteFsConnector, self).__init__(driver, execute, root_helper,
*args, **kwargs)
def set_execute(self, execute):
super(RemoteFsConnector, self).set_execute(execute)
self._remotefsclient.set_execute(execute)
def connect_volume(self, connection_properties):
"""Ensure that the filesystem containing the volume is mounted.
connection_properties must include:
export - remote filesystem device (e.g. '172.18.194.100:/var/nfs')
name - file name within the filesystem
connection_properties may optionally include:
options - options to pass to mount
"""
mnt_flags = []
if 'options' in connection_properties:
mnt_flags = connection_properties['options'].split()
nfs_share = connection_properties['export']
self._remotefsclient.mount(nfs_share, mnt_flags)
mount_point = self._remotefsclient.get_mount_point(nfs_share)
path = mount_point + '/' + connection_properties['name']
return {'path': path}
def disconnect_volume(self, connection_properties, device_info):
"""No need to do anything to disconnect a volume in a filesystem."""
pass

View File

@ -0,0 +1,16 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 OpenStack Foundation
# All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

View File

@ -0,0 +1,112 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (c) 2013 OpenStack Foundation
# All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Remote filesystem client utilities."""
import hashlib
import os
from oslo.config import cfg
from cinder import exception
from cinder.openstack.common.gettextutils import _
from cinder.openstack.common import log as logging
from cinder.openstack.common import processutils as putils
LOG = logging.getLogger(__name__)
remotefs_client_opts = [
cfg.StrOpt('nfs_mount_point_base',
default='$state_path/mnt',
help='Base dir containing mount points for nfs shares'),
cfg.StrOpt('nfs_mount_options',
default=None,
help='Mount options passed to the nfs client. See section '
'of the nfs man page for details'),
cfg.StrOpt('glusterfs_mount_point_base',
default='$state_path/mnt',
help='Base dir containing mount points for gluster shares'),
]
CONF = cfg.CONF
CONF.register_opts(remotefs_client_opts)
class RemoteFsClient(object):
def __init__(self, mount_type, execute=putils.execute,
root_helper="sudo", *args, **kwargs):
self._mount_type = mount_type
if mount_type == "nfs":
self._mount_base = CONF.nfs_mount_point_base
self._mount_options = CONF.nfs_mount_options
elif mount_type == "glusterfs":
self._mount_base = CONF.glusterfs_mount_point_base
self._mount_options = None
else:
raise exception.ProtocolNotSupported(protocol=mount_type)
self.root_helper = root_helper
self.set_execute(execute)
def set_execute(self, execute):
self._execute = execute
def _get_hash_str(self, base_str):
"""Return a string that represents hash of base_str
(in a hex format).
"""
return hashlib.md5(base_str).hexdigest()
def get_mount_point(self, device_name):
"""
:param device_name: example 172.18.194.100:/var/nfs
"""
return os.path.join(self._mount_base,
self._get_hash_str(device_name))
def _read_mounts(self):
(out, err) = self._execute('mount', check_exit_code=0)
lines = out.split('\n')
mounts = {}
for line in lines:
tokens = line.split()
if 2 < len(tokens):
device = tokens[0]
mnt_point = tokens[2]
mounts[mnt_point] = device
return mounts
def mount(self, nfs_share, flags=None):
"""Mount NFS share."""
mount_path = self.get_mount_point(nfs_share)
if mount_path in self._read_mounts():
LOG.info(_('Already mounted: %s') % mount_path)
return
self._execute('mkdir', '-p', mount_path, check_exit_code=0)
mnt_cmd = ['mount', '-t', self._mount_type]
if self._mount_options is not None:
mnt_cmd.extend(['-o', self._mount_options])
if flags is not None:
mnt_cmd.extend(flags)
mnt_cmd.extend([nfs_share, mount_path])
self._execute(*mnt_cmd, root_helper=self.root_helper,
run_as_root=True, check_exit_code=0)

View File

@ -25,6 +25,7 @@ from cinder.brick.initiator import connector
from cinder.brick.initiator import host_driver
from cinder.brick.initiator import linuxfc
from cinder.brick.initiator import linuxscsi
from cinder.brick.remotefs import remotefs
from cinder.openstack.common import log as logging
from cinder.openstack.common import loopingcall
from cinder.openstack.common import processutils as putils
@ -67,6 +68,14 @@ class ConnectorTestCase(test.TestCase):
self.assertTrue(obj.__class__.__name__,
"AoEConnector")
obj = connector.InitiatorConnector.factory('nfs', None)
self.assertTrue(obj.__class__.__name__,
"RemoteFsConnector")
obj = connector.InitiatorConnector.factory('glusterfs', None)
self.assertTrue(obj.__class__.__name__,
"RemoteFsConnector")
self.assertRaises(ValueError,
connector.InitiatorConnector.factory,
"bogus", None)
@ -543,3 +552,44 @@ class AoEConnectorTestCase(ConnectorTestCase):
self.mox.ReplayAll()
self.connector.disconnect_volume(self.connection_properties, {})
class RemoteFsConnectorTestCase(ConnectorTestCase):
"""Test cases for Remote FS initiator class."""
TEST_DEV = '172.18.194.100:/var/nfs'
TEST_PATH = '/mnt/test/df0808229363aad55c27da50c38d6328'
def setUp(self):
super(RemoteFsConnectorTestCase, self).setUp()
self.mox = mox.Mox()
self.connection_properties = {
'export': self.TEST_DEV,
'name': '9c592d52-ce47-4263-8c21-4ecf3c029cdb'}
self.connector = connector.RemoteFsConnector('nfs', root_helper='sudo')
self.connector._remotefsclient._mount_options = None
self.connector._remotefsclient._mount_base = '/mnt/test'
def tearDown(self):
self.mox.VerifyAll()
self.mox.UnsetStubs()
super(RemoteFsConnectorTestCase, self).tearDown()
def test_connect_volume(self):
"""Test the basic connect volume case."""
client = self.connector._remotefsclient
self.mox.StubOutWithMock(client, '_execute')
client._execute('mount',
check_exit_code=0).AndReturn(("", ""))
client._execute('mkdir', '-p', self.TEST_PATH,
check_exit_code=0).AndReturn(("", ""))
client._execute('mount', '-t', 'nfs',
self.TEST_DEV, self.TEST_PATH,
root_helper='sudo', run_as_root=True,
check_exit_code=0).AndReturn(("", ""))
self.mox.ReplayAll()
self.connector.connect_volume(self.connection_properties)
def test_disconnect_volume(self):
"""Nothing should happen here -- make sure it doesn't blow up."""
self.connector.disconnect_volume(self.connection_properties, {})

View File

@ -0,0 +1,82 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# (c) Copyright 2013 OpenStack Foundation
# All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mox
from cinder.brick.remotefs import remotefs
from cinder.openstack.common import log as logging
from cinder.openstack.common import processutils as putils
from cinder import test
LOG = logging.getLogger(__name__)
class BrickRemoteFsTestCase(test.TestCase):
TEST_EXPORT = '1.2.3.4/export1'
TEST_MNT_BASE = '/mnt/test'
TEST_HASH = '4d664fd43b6ff86d80a4ea969c07b3b9'
TEST_MNT_POINT = TEST_MNT_BASE + '/' + TEST_HASH
def setUp(self):
super(BrickRemoteFsTestCase, self).setUp()
self._mox = mox.Mox()
self._nfsclient = remotefs.RemoteFsClient('nfs')
self._nfsclient._mount_options = None
self._nfsclient._mount_base = self.TEST_MNT_BASE
self.addCleanup(self._mox.UnsetStubs)
def test_get_hash_str(self):
"""_get_hash_str should calculation correct value."""
self.assertEqual(self.TEST_HASH,
self._nfsclient._get_hash_str(self.TEST_EXPORT))
def test_get_mount_point(self):
mnt_point = self._nfsclient.get_mount_point(self.TEST_EXPORT)
self.assertEqual(mnt_point, self.TEST_MNT_POINT)
def test_mount_nfs_should_mount_correctly(self):
mox = self._mox
client = self._nfsclient
mox.StubOutWithMock(client, '_execute')
client._execute('mount', check_exit_code=0).AndReturn(("", ""))
client._execute('mkdir', '-p', self.TEST_MNT_POINT,
check_exit_code=0).AndReturn(("", ""))
client._execute('mount', '-t', 'nfs', self.TEST_EXPORT,
self.TEST_MNT_POINT,
root_helper='sudo', run_as_root=True,
check_exit_code=0).AndReturn(("", ""))
mox.ReplayAll()
client.mount(self.TEST_EXPORT)
mox.VerifyAll()
def test_mount_nfs_should_not_remount(self):
mox = self._mox
client = self._nfsclient
line = "%s on %s type nfs (rw)\n" % (self.TEST_EXPORT,
self.TEST_MNT_POINT)
mox.StubOutWithMock(client, '_execute')
client._execute('mount', check_exit_code=0).AndReturn((line, ""))
mox.ReplayAll()
client.mount(self.TEST_EXPORT)
mox.VerifyAll()

View File

@ -47,7 +47,6 @@ class DumbVolume(object):
class RemoteFsDriverTestCase(test.TestCase):
TEST_EXPORT = '1.2.3.4/export1'
TEST_FILE_NAME = 'test.txt'
def setUp(self):
@ -110,13 +109,6 @@ class RemoteFsDriverTestCase(test.TestCase):
mox.VerifyAll()
def test_get_hash_str(self):
"""_get_hash_str should calculation correct value."""
drv = self._driver
self.assertEqual('4d664fd43b6ff86d80a4ea969c07b3b9',
drv._get_hash_str(self.TEST_EXPORT))
class NfsDriverTestCase(test.TestCase):
"""Test case for NFS driver."""
@ -140,13 +132,13 @@ class NfsDriverTestCase(test.TestCase):
self.configuration = mox_lib.MockObject(conf.Configuration)
self.configuration.append_config_values(mox_lib.IgnoreArg())
self.configuration.nfs_shares_config = None
self.configuration.nfs_mount_options = None
self.configuration.nfs_mount_point_base = '$state_path/mnt'
self.configuration.nfs_sparsed_volumes = True
self.configuration.nfs_used_ratio = 0.95
self.configuration.nfs_oversub_ratio = 1.0
self._driver = nfs.NfsDriver(configuration=self.configuration)
self._driver.shares = {}
self._driver._remotefsclient._mount_options = None
self._driver._remotefsclient._mount_base = self.TEST_MNT_POINT_BASE
self.addCleanup(self.stubs.UnsetAll)
self.addCleanup(self._mox.UnsetStubs)
@ -168,22 +160,6 @@ class NfsDriverTestCase(test.TestCase):
'/mnt/test/2f4f60214cf43c595666dd815f0360a4/volume-123',
drv.local_path(volume))
def test_mount_nfs_should_mount_correctly(self):
"""_mount_nfs common case usage."""
mox = self._mox
drv = self._driver
mox.StubOutWithMock(drv, '_execute')
drv._execute('mkdir', '-p', self.TEST_MNT_POINT)
drv._execute('mount', '-t', 'nfs', self.TEST_NFS_EXPORT1,
self.TEST_MNT_POINT, run_as_root=True)
mox.ReplayAll()
drv._mount_nfs(self.TEST_NFS_EXPORT1, self.TEST_MNT_POINT)
mox.VerifyAll()
def test_copy_image_to_volume(self):
"""resize_image common case usage."""
mox = self._mox
@ -215,86 +191,6 @@ class NfsDriverTestCase(test.TestCase):
mox.VerifyAll()
def test_mount_nfs_should_suppress_already_mounted_error(self):
"""_mount_nfs should suppress already mounted error if ensure=True
"""
mox = self._mox
drv = self._driver
mox.StubOutWithMock(drv, '_execute')
drv._execute('mkdir', '-p', self.TEST_MNT_POINT)
drv._execute('mount', '-t', 'nfs', self.TEST_NFS_EXPORT1,
self.TEST_MNT_POINT, run_as_root=True).\
AndRaise(putils.ProcessExecutionError(
stderr='is busy or already mounted'))
mox.ReplayAll()
drv._mount_nfs(self.TEST_NFS_EXPORT1, self.TEST_MNT_POINT, ensure=True)
mox.VerifyAll()
def test_mount_nfs_should_reraise_already_mounted_error(self):
"""_mount_nfs should not suppress already mounted error if ensure=False
"""
mox = self._mox
drv = self._driver
mox.StubOutWithMock(drv, '_execute')
drv._execute('mkdir', '-p', self.TEST_MNT_POINT)
drv._execute(
'mount',
'-t',
'nfs',
self.TEST_NFS_EXPORT1, self.TEST_MNT_POINT, run_as_root=True).\
AndRaise(putils.ProcessExecutionError(stderr='is busy or '
'already mounted'))
mox.ReplayAll()
self.assertRaises(putils.ProcessExecutionError, drv._mount_nfs,
self.TEST_NFS_EXPORT1, self.TEST_MNT_POINT,
ensure=False)
mox.VerifyAll()
def test_mount_nfs_should_create_mountpoint_if_not_yet(self):
"""_mount_nfs should create mountpoint if it doesn't exist."""
mox = self._mox
drv = self._driver
mox.StubOutWithMock(drv, '_execute')
drv._execute('mkdir', '-p', self.TEST_MNT_POINT)
drv._execute(*([IgnoreArg()] * 5), run_as_root=IgnoreArg())
mox.ReplayAll()
drv._mount_nfs(self.TEST_NFS_EXPORT1, self.TEST_MNT_POINT)
mox.VerifyAll()
def test_mount_nfs_should_not_create_mountpoint_if_already(self):
"""_mount_nfs should not create mountpoint if it already exists."""
mox = self._mox
drv = self._driver
mox.StubOutWithMock(drv, '_execute')
drv._execute('mkdir', '-p', self.TEST_MNT_POINT)
drv._execute(*([IgnoreArg()] * 5), run_as_root=IgnoreArg())
mox.ReplayAll()
drv._mount_nfs(self.TEST_NFS_EXPORT1, self.TEST_MNT_POINT)
mox.VerifyAll()
def test_get_hash_str(self):
"""_get_hash_str should calculation correct value."""
drv = self._driver
self.assertEqual('2f4f60214cf43c595666dd815f0360a4',
drv._get_hash_str(self.TEST_NFS_EXPORT1))
def test_get_mount_point_for_share(self):
"""_get_mount_point_for_share should calculate correct value."""
drv = self._driver
@ -398,24 +294,6 @@ class NfsDriverTestCase(test.TestCase):
mox.VerifyAll()
def test_ensure_share_mounted(self):
"""_ensure_share_mounted simple use case."""
mox = self._mox
drv = self._driver
mox.StubOutWithMock(drv, '_get_mount_point_for_share')
drv._get_mount_point_for_share(self.TEST_NFS_EXPORT1).\
AndReturn(self.TEST_MNT_POINT)
mox.StubOutWithMock(drv, '_mount_nfs')
drv._mount_nfs(self.TEST_NFS_EXPORT1, self.TEST_MNT_POINT, ensure=True)
mox.ReplayAll()
drv._ensure_share_mounted(self.TEST_NFS_EXPORT1)
mox.VerifyAll()
def test_ensure_shares_mounted_should_save_mounting_successfully(self):
"""_ensure_shares_mounted should save share if mounted with success."""
mox = self._mox

View File

@ -16,12 +16,14 @@
# under the License.
import errno
import hashlib
import json
import os
import re
from oslo.config import cfg
from cinder.brick.remotefs import remotefs
from cinder import db
from cinder import exception
from cinder.image import image_utils
@ -34,9 +36,6 @@ volume_opts = [
cfg.StrOpt('glusterfs_shares_config',
default='/etc/cinder/glusterfs_shares',
help='File with the list of available gluster shares'),
cfg.StrOpt('glusterfs_mount_point_base',
default='$state_path/mnt',
help='Base dir containing mount points for gluster shares'),
cfg.StrOpt('glusterfs_disk_util',
default='df',
help='Use du or df for free space calculation'),
@ -68,6 +67,7 @@ class GlusterfsDriver(nfs.RemoteFsDriver):
def __init__(self, *args, **kwargs):
super(GlusterfsDriver, self).__init__(*args, **kwargs)
self.configuration.append_config_values(volume_opts)
self.configuration.append_config_values(remotefs.remotefs_client_opts)
def do_setup(self, context):
"""Any initialization the volume driver does while starting."""
@ -795,6 +795,12 @@ class GlusterfsDriver(nfs.RemoteFsDriver):
volume_size=volume_size_for)
return greatest_share
def _get_hash_str(self, base_str):
"""Return a string that represents hash of base_str
(in a hex format).
"""
return hashlib.md5(base_str).hexdigest()
def _get_mount_point_for_share(self, glusterfs_share):
"""Return mount point for share.
:param glusterfs_share: example 172.18.194.100:/var/glusterfs

View File

@ -16,15 +16,15 @@
# under the License.
import errno
import hashlib
import os
from oslo.config import cfg
from cinder.brick.remotefs import remotefs
from cinder import exception
from cinder.image import image_utils
from cinder.openstack.common import log as logging
from cinder.openstack.common import processutils
from cinder.openstack.common import processutils as putils
from cinder import units
from cinder.volume import driver
@ -36,18 +36,11 @@ volume_opts = [
cfg.StrOpt('nfs_shares_config',
default='/etc/cinder/nfs_shares',
help='File with the list of available nfs shares'),
cfg.StrOpt('nfs_mount_point_base',
default='$state_path/mnt',
help='Base dir containing mount points for nfs shares'),
cfg.BoolOpt('nfs_sparsed_volumes',
default=True,
help=('Create volumes as sparsed files which take no space.'
'If set to False volume is created as regular file.'
'In such case volume creation takes a lot of time.')),
cfg.StrOpt('nfs_mount_options',
default=None,
help='Mount options passed to the nfs client. See section '
'of the nfs man page for details'),
cfg.FloatOpt('nfs_used_ratio',
default=0.95,
help=('Percent of ACTUAL usage of the underlying volume '
@ -216,12 +209,6 @@ class RemoteFsDriver(driver.VolumeDriver):
return os.path.join(self._get_mount_point_for_share(nfs_share),
volume['name'])
def _get_hash_str(self, base_str):
"""returns string that represents hash of base_str
(in a hex format).
"""
return hashlib.md5(base_str).hexdigest()
def copy_image_to_volume(self, context, volume, image_service, image_id):
"""Fetch the image from image_service and write it to the volume."""
image_utils.fetch_to_raw(context,
@ -334,7 +321,7 @@ class RemoteFsDriver(driver.VolumeDriver):
"""
try:
self._execute(*cmd, run_as_root=True)
except processutils.ProcessExecutionError as exc:
except putils.ProcessExecutionError as exc:
if ensure and 'already mounted' in exc.stderr:
LOG.warn(_("%s is already mounted"), share)
else:
@ -368,9 +355,16 @@ class NfsDriver(RemoteFsDriver):
volume_backend_name = 'Generic_NFS'
VERSION = VERSION
def __init__(self, *args, **kwargs):
def __init__(self, execute=putils.execute, *args, **kwargs):
self._remotefsclient = None
super(NfsDriver, self).__init__(*args, **kwargs)
self.configuration.append_config_values(volume_opts)
self._remotefsclient = remotefs.RemoteFsClient('nfs', execute)
def set_execute(self, execute):
super(NfsDriver, self).set_execute(execute)
if self._remotefsclient:
self._remotefsclient.set_execute(execute)
def do_setup(self, context):
"""Any initialization the volume driver does while starting"""
@ -412,8 +406,10 @@ class NfsDriver(RemoteFsDriver):
raise
def _ensure_share_mounted(self, nfs_share):
mount_path = self._get_mount_point_for_share(nfs_share)
self._mount_nfs(nfs_share, mount_path, ensure=True)
mnt_flags = []
if self.shares.get(nfs_share) is not None:
mnt_flags = self.shares[nfs_share].split()
self._remotefsclient.mount(nfs_share, mnt_flags)
def _find_share(self, volume_size_in_gib):
"""Choose NFS share among available ones for given volume size.
@ -482,11 +478,8 @@ class NfsDriver(RemoteFsDriver):
return target_share
def _get_mount_point_for_share(self, nfs_share):
"""
:param nfs_share: example 172.18.194.100:/var/nfs
"""
return os.path.join(self.configuration.nfs_mount_point_base,
self._get_hash_str(nfs_share))
"""Needed by parent class."""
return self._remotefsclient.get_mount_point(nfs_share)
def _get_capacity_info(self, nfs_share):
"""Calculate available space on the NFS share.
@ -504,17 +497,3 @@ class NfsDriver(RemoteFsDriver):
'*snapshot*', mount_point, run_as_root=True)
total_allocated = float(du.split()[0])
return total_size, total_available, total_allocated
def _mount_nfs(self, nfs_share, mount_path, ensure=False):
"""Mount NFS share to mount path."""
self._execute('mkdir', '-p', mount_path)
# Construct the NFS mount command.
nfs_cmd = ['mount', '-t', 'nfs']
if self.configuration.nfs_mount_options is not None:
nfs_cmd.extend(['-o', self.configuration.nfs_mount_options])
if self.shares.get(nfs_share) is not None:
nfs_cmd.extend(self.shares[nfs_share].split())
nfs_cmd.extend([nfs_share, mount_path])
self._do_mount(nfs_cmd, ensure, nfs_share)

View File

@ -273,6 +273,23 @@
#volumes_dir=$state_path/volumes
#
# Options defined in cinder.brick.remotefs.remotefs
#
# Base dir containing mount points for nfs shares (string
# value)
#nfs_mount_point_base=$state_path/mnt
# Mount options passed to the nfs client. See section of the
# nfs man page for details (string value)
#nfs_mount_options=<None>
# Base dir containing mount points for gluster shares (string
# value)
#glusterfs_mount_point_base=$state_path/mnt
#
# Options defined in cinder.common.config
#
@ -1103,10 +1120,6 @@
# value)
#glusterfs_shares_config=/etc/cinder/glusterfs_shares
# Base dir containing mount points for gluster shares (string
# value)
#glusterfs_mount_point_base=$state_path/mnt
# Use du or df for free space calculation (string value)
#glusterfs_disk_util=df
@ -1266,19 +1279,11 @@
# File with the list of available nfs shares (string value)
#nfs_shares_config=/etc/cinder/nfs_shares
# Base dir containing mount points for nfs shares (string
# value)
#nfs_mount_point_base=$state_path/mnt
# Create volumes as sparsed files which take no space.If set
# to False volume is created as regular file.In such case
# volume creation takes a lot of time. (boolean value)
#nfs_sparsed_volumes=true
# Mount options passed to the nfs client. See section of the
# nfs man page for details (string value)
#nfs_mount_options=<None>
# Percent of ACTUAL usage of the underlying volume before no
# new volumes can be allocated to the volume destination.
# (floating point value)