Skip to content

Commit

Permalink
Support for NFS shares with spaces in path.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Anton Frolov committed May 29, 2013
1 parent b782597 commit 9246407
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 14 deletions.
51 changes: 42 additions & 9 deletions cinder/tests/test_nfs.py
Expand Up @@ -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()
Expand Down Expand Up @@ -261,12 +263,9 @@ def test_get_capacity_info(self):
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
Expand All @@ -276,8 +275,9 @@ def test_get_capacity_info(self):
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*',
Expand All @@ -286,11 +286,44 @@ def test_get_capacity_info(self):

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
Expand Down
10 changes: 5 additions & 5 deletions cinder/volume/drivers/nfs.py
Expand Up @@ -152,7 +152,7 @@ def _load_shares_config(self, share_file):
# 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
Expand Down Expand Up @@ -384,11 +384,11 @@ def _get_capacity_info(self, nfs_share):
"""
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)
Expand Down

0 comments on commit 9246407

Please sign in to comment.