Support for NFS shares with spaces in path.

Unescape share address string listed in nfs_shares_config so that
'x.y.z.w:/foo\040bar' would become 'x.y.z.w:/foo bar' to support
mounting shares with spaces in name.
Use stat command to get available and total space on device instead
of df since it's output is easier to parse.

Fixes: bug #1180984
Change-Id: I552aba91ca8db14130f854c739594a818186bbe2
This commit is contained in:
Anton Frolov 2013-05-28 19:34:41 +04:00
parent b782597725
commit 924640705c
2 changed files with 47 additions and 14 deletions

View File

@ -115,6 +115,8 @@ class NfsDriverTestCase(test.TestCase):
TEST_LOCAL_PATH = '/mnt/nfs/volume-123'
TEST_FILE_NAME = 'test.txt'
TEST_SHARES_CONFIG_FILE = '/etc/cinder/test-shares.conf'
TEST_NFS_EXPORT_SPACES = 'nfs-host3:/export this'
TEST_MNT_POINT_SPACES = '/ 0 0 0 /foo'
def setUp(self):
super(NfsDriverTestCase, self).setUp()
@ -261,12 +263,9 @@ class NfsDriverTestCase(test.TestCase):
mox = self._mox
drv = self._driver
df_total_size = 2620544
df_avail = 2129984
df_head = 'Filesystem 1K-blocks Used Available Use% Mounted on\n'
df_data = 'nfs-host:/export %d 996864 %d 41%% /mnt' % (df_total_size,
df_avail)
df_output = df_head + df_data
stat_total_size = 2620544
stat_avail = 2129984
stat_output = '1 %d %d' % (stat_total_size, stat_avail)
du_used = 490560
du_output = '%d /mnt' % du_used
@ -276,8 +275,9 @@ class NfsDriverTestCase(test.TestCase):
AndReturn(self.TEST_MNT_POINT)
mox.StubOutWithMock(drv, '_execute')
drv._execute('df', '-P', '-B', '1', self.TEST_MNT_POINT,
run_as_root=True).AndReturn((df_output, None))
drv._execute('stat', '-f', '-c', '%S %b %a',
self.TEST_MNT_POINT,
run_as_root=True).AndReturn((stat_output, None))
drv._execute('du', '-sb', '--apparent-size',
'--exclude', '*snapshot*',
@ -286,11 +286,44 @@ class NfsDriverTestCase(test.TestCase):
mox.ReplayAll()
self.assertEquals((df_total_size, df_avail, du_used),
self.assertEquals((stat_total_size, stat_avail, du_used),
drv._get_capacity_info(self.TEST_NFS_EXPORT1))
mox.VerifyAll()
def test_get_capacity_info_for_share_and_mount_point_with_spaces(self):
"""_get_capacity_info should calculate correct value."""
mox = self._mox
drv = self._driver
stat_total_size = 2620544
stat_avail = 2129984
stat_output = '1 %d %d' % (stat_total_size, stat_avail)
du_used = 490560
du_output = '%d /mnt' % du_used
mox.StubOutWithMock(drv, '_get_mount_point_for_share')
drv._get_mount_point_for_share(self.TEST_NFS_EXPORT_SPACES).\
AndReturn(self.TEST_MNT_POINT_SPACES)
mox.StubOutWithMock(drv, '_execute')
drv._execute('stat', '-f', '-c', '%S %b %a',
self.TEST_MNT_POINT_SPACES,
run_as_root=True).AndReturn((stat_output, None))
drv._execute('du', '-sb', '--apparent-size',
'--exclude', '*snapshot*',
self.TEST_MNT_POINT_SPACES,
run_as_root=True).AndReturn((du_output, None))
mox.ReplayAll()
self.assertEquals((stat_total_size, stat_avail, du_used),
drv._get_capacity_info(self.TEST_NFS_EXPORT_SPACES))
mox.VerifyAll()
def test_load_shares_config(self):
mox = self._mox
drv = self._driver

View File

@ -152,7 +152,7 @@ class RemoteFsDriver(driver.VolumeDriver):
# results in share_info =
# [ 'address:/vol', '-o options=123,rw --other' ]
share_address = share_info[0].strip()
share_address = share_info[0].strip().decode('unicode_escape')
share_opts = share_info[1].strip() if len(share_info) > 1 else None
self.shares[share_address] = share_opts
@ -384,11 +384,11 @@ class NfsDriver(RemoteFsDriver):
"""
mount_point = self._get_mount_point_for_share(nfs_share)
df, _ = self._execute('df', '-P', '-B', '1', mount_point,
df, _ = self._execute('stat', '-f', '-c', '%S %b %a', mount_point,
run_as_root=True)
df = df.splitlines()[1]
total_available = float(df.split()[3])
total_size = float(df.split()[1])
block_size, blocks_total, blocks_avail = map(float, df.split())
total_available = block_size * blocks_avail
total_size = block_size * blocks_total
du, _ = self._execute('du', '-sb', '--apparent-size', '--exclude',
'*snapshot*', mount_point, run_as_root=True)