Merge "Fix get_stats to return real used space in HNAS"

This commit is contained in:
Jenkins 2015-09-17 02:41:14 +00:00 committed by Gerrit Code Review
commit cc66f22781
2 changed files with 80 additions and 74 deletions

View File

@ -48,24 +48,26 @@ class HNASSSHBackend(object):
def get_stats(self): def get_stats(self):
"""Get the stats from file-system. """Get the stats from file-system.
The available space is calculated by total space - SUM(quotas).
:returns: :returns:
total_fs_space = Total size from filesystem in config file. fs_capacity.size = Total size from filesystem.
available_space = Free space currently on filesystem. available_space = Free space currently on filesystem.
""" """
total_fs_space = self._get_filesystem_capacity() command = ['df', '-a', '-f', self.fs_name]
total_quota = 0 output, err = self._execute(command)
share_list = self._get_vvol_list()
for item in share_list: line = output.split('\n')
share_quota = self._get_share_quota(item) fs_capacity = Capacity(line[3])
if share_quota is not None:
total_quota += share_quota available_space = fs_capacity.size - fs_capacity.used
available_space = total_fs_space - total_quota
LOG.debug("Available space in the file system: %(space)s.", LOG.debug("Total space in file system: %(total)s GB.",
{'total': fs_capacity.size})
LOG.debug("Used space in the file system: %(used)s GB.",
{'used': fs_capacity.used})
LOG.debug("Available space in the file system: %(space)s GB.",
{'space': available_space}) {'space': available_space})
return total_fs_space, available_space return fs_capacity.size, available_space
def allow_access(self, share_id, host, share_proto, permission='rw'): def allow_access(self, share_id, host, share_proto, permission='rw'):
"""Allow access to the share. """Allow access to the share.
@ -674,38 +676,6 @@ class HNASSSHBackend(object):
# Returns None if the quota is unset # Returns None if the quota is unset
return None return None
def _get_vvol_list(self):
command = ['virtual-volume', 'list', self.fs_name]
output, err = self._execute(command)
vvol_list = []
items = output.split('\n')
for i in range(0, len(items) - 1):
if ":" not in items[i]:
vvol_list.append(items[i])
return vvol_list
def _get_filesystem_capacity(self):
command = ['filesystem-limits', self.fs_name]
output, err = self._execute(command)
items = output.split('\n')
for i in range(0, len(items) - 1):
if 'Current capacity' in items[i]:
fs_capacity = items[i].split(' ')
# Gets the index of the file system capacity (EX: 20GiB)
index = [i for i, string in enumerate(fs_capacity)
if 'GiB' in string]
fs_capacity = fs_capacity[index[0]]
fs_capacity = fs_capacity.split('GiB')[0]
return int(fs_capacity)
@mutils.synchronized("hds_hnas_select_fs", external=True) @mutils.synchronized("hds_hnas_select_fs", external=True)
def _locked_selectfs(self, op, path): def _locked_selectfs(self, op, path):
if op == 'create': if op == 'create':
@ -827,3 +797,20 @@ class JobSubmit(object):
self.request_status = " ".join(split_data[1:4]) self.request_status = " ".join(split_data[1:4])
self.job_id = split_data[8] self.job_id = split_data[8]
class Capacity(object):
def __init__(self, data):
if data:
items = data.split()
self.id = items[0]
self.label = items[1]
self.evs = items[2]
self.size = float(items[3])
self.size_measure = items[4]
if self.size_measure == 'TB':
self.size = self.size * units.Ki
self.used = float(items[5])
self.used_measure = items[6]
if self.used_measure == 'TB':
self.used = self.used * units.Ki

View File

@ -381,6 +381,24 @@ HNAS_RESULT_job_running = """JOB ID : ab4211b8-aac8-11ce-91af-39e0822ea368
block special devices, 25 character devices block special devices, 25 character devices
""" """
HNAS_RESULT_df = """
ID Label EVS Size Used Snapshots Deduped \
Avail Thin ThinSize ThinAvail FS Type
---- ------------- --- -------- -------------- --------- ------- \
------------- ---- -------- --------- -------------------
1051 FS-ManilaDev1 3 70.00 GB 10.00 GB (75%) 0 B (0%) NA \
18.3 GB (25%) No 4 KB,WFS-2,128 DSBs
"""
HNAS_RESULT_df_tb = """
ID Label EVS Size Used Snapshots Deduped \
Avail Thin ThinSize ThinAvail FS Type
---- ------------- --- -------- -------------- --------- ------- \
------------- ---- -------- --------- -------------------
1051 FS-ManilaDev1 3.00 7.00 TB 2 TB (75%) 0 B (0%) NA \
18.3 GB (25%) No 4 KB,WFS-2,128 DSBs
"""
class HNASSSHTestCase(test.TestCase): class HNASSSHTestCase(test.TestCase):
def setUp(self): def setUp(self):
@ -422,37 +440,44 @@ class HNASSSHTestCase(test.TestCase):
} }
def test_get_stats(self): def test_get_stats(self):
fake_list_command = ['quota', 'list', 'file_system', 'vol3'] fake_list_command = ['df', '-a', '-f', 'file_system']
expected_debug_calls = [
('Total space in file system: %(total)s GB.', {'total': 7168.0}),
('Used space in the file system: %(used)s GB.', {'used': 2048.0}),
('Available space in the file system: %(space)s GB.',
{'space': 5120.0})
]
self.mock_object(ssh.HNASSSHBackend, '_execute', self.mock_object(ssh.HNASSSHBackend, '_execute',
mock.Mock(side_effect=[(HNAS_RESULT_fslimits, ""), mock.Mock(return_value=(HNAS_RESULT_df_tb, "")))
(HNAS_RESULT_vvol_list, ""),
(HNAS_RESULT_quota, ""),
(HNAS_RESULT_quota, ""),
(HNAS_RESULT_quota, ""),
(HNAS_RESULT_vvol_list, "")]))
total, free = self._driver.get_stats() total, free = self._driver.get_stats()
ssh.HNASSSHBackend._execute.assert_called_with(fake_list_command) ssh.HNASSSHBackend._execute.assert_called_with(fake_list_command)
self.assertTrue(self.mock_log.debug.called) self.mock_log.debug.assert_has_calls([mock.call(*a) for a in
self.assertEqual(100, total) expected_debug_calls])
self.assertEqual(85, free) self.assertEqual(7168.0, total)
self.assertEqual(5120.0, free)
def test_get_stats_terabytes(self): def test_get_stats_terabytes(self):
fake_list_command = ['quota', 'list', 'file_system', 'vol3'] fake_list_command = ['df', '-a', '-f', 'file_system']
expected_debug_calls = [
('Total space in file system: %(total)s GB.', {'total': 7168.0}),
('Used space in the file system: %(used)s GB.', {'used': 2048.0}),
('Available space in the file system: %(space)s GB.',
{'space': 5120.0})
]
self.mock_object(ssh.HNASSSHBackend, '_execute', self.mock_object(ssh.HNASSSHBackend, '_execute',
mock.Mock(side_effect=[(HNAS_RESULT_fslimits_tb, ""), mock.Mock(return_value=(HNAS_RESULT_df_tb, "")))
(HNAS_RESULT_vvol_list, ""),
(HNAS_RESULT_quota, ""),
(HNAS_RESULT_quota_tb, ""),
(HNAS_RESULT_quota, "")]))
total, free = self._driver.get_stats() total, free = self._driver.get_stats()
ssh.HNASSSHBackend._execute.assert_called_with(fake_list_command) ssh.HNASSSHBackend._execute.assert_called_with(fake_list_command)
self.assertTrue(self.mock_log.debug.called) self.mock_log.debug.assert_has_calls([mock.call(*a) for a in
self.assertEqual(1500, total) expected_debug_calls])
self.assertEqual(466, free) self.assertEqual(7168.0, total)
self.assertEqual(5120.0, free)
def test_allow_access(self): def test_allow_access(self):
fake_mod_command = ['nfs-export', 'mod', '-c', fake_mod_command = ['nfs-export', 'mod', '-c',
@ -836,9 +861,7 @@ class HNASSSHTestCase(test.TestCase):
(HNAS_RESULT_vvol, ""), (HNAS_RESULT_vvol, ""),
(HNAS_RESULT_quota, ""), (HNAS_RESULT_quota, ""),
(HNAS_RESULT_export, ""), (HNAS_RESULT_export, ""),
(HNAS_RESULT_fslimits, ""), (HNAS_RESULT_df, ""),
(HNAS_RESULT_vvol, ""),
(HNAS_RESULT_quota, ""),
(HNAS_RESULT_empty, "")])) (HNAS_RESULT_empty, "")]))
self._driver.extend_share(self.vvol['id'], self._driver.extend_share(self.vvol['id'],
@ -850,18 +873,14 @@ class HNASSSHTestCase(test.TestCase):
ssh.HNASSSHBackend._execute.assert_called_with(fake_quota_mod_command) ssh.HNASSSHBackend._execute.assert_called_with(fake_quota_mod_command)
def test_extend_share_no_space(self): def test_extend_share_no_space(self):
fake_list_command = ['quota', 'list', 'file_system', 'vol3'] fake_list_command = ['df', '-a', '-f', 'file_system']
self.mock_object(ssh.HNASSSHBackend, '_execute', self.mock_object(ssh.HNASSSHBackend, '_execute',
mock.Mock(side_effect=[(HNAS_RESULT_fs, ""), mock.Mock(side_effect=[(HNAS_RESULT_fs, ""),
(HNAS_RESULT_fs, ""), (HNAS_RESULT_fs, ""),
(HNAS_RESULT_vvol, ""), (HNAS_RESULT_vvol, ""),
(HNAS_RESULT_quota, ""), (HNAS_RESULT_quota, ""),
(HNAS_RESULT_export, ""), (HNAS_RESULT_export, ""),
(HNAS_RESULT_fslimits, ""), (HNAS_RESULT_df, "")]))
(HNAS_RESULT_vvol_list, ""),
(HNAS_RESULT_quota, ""),
(HNAS_RESULT_quota, ""),
(HNAS_RESULT_quota, "")]))
# Tests when try to create a share bigger than available free space # Tests when try to create a share bigger than available free space
self.assertRaises(exception.HNASBackendException, self.assertRaises(exception.HNASBackendException,
@ -879,13 +898,13 @@ class HNASSSHTestCase(test.TestCase):
(HNAS_RESULT_vvol, ""), (HNAS_RESULT_vvol, ""),
(HNAS_RESULT_quota, ""), (HNAS_RESULT_quota, ""),
(HNAS_RESULT_export, ""), (HNAS_RESULT_export, ""),
(HNAS_RESULT_quota, "")])) (HNAS_RESULT_quota_tb, "")]))
output = self._driver.manage_existing(self.vvol, self.vvol['id']) output = self._driver.manage_existing(self.vvol, self.vvol['id'])
self.assertEqual({'export_locations': self.assertEqual({'export_locations':
['172.24.44.1:/shares/vvol_test'], ['172.24.44.1:/shares/vvol_test'],
'size': 5.0}, output) 'size': 1024.0}, output)
ssh.HNASSSHBackend._execute.assert_called_with(fake_list_command) ssh.HNASSSHBackend._execute.assert_called_with(fake_list_command)
def test_manage_existing_share_without_size(self): def test_manage_existing_share_without_size(self):