Fix HNAS error with unconfined filesystems

Unconfined filesystems created through CLI in HNAS caused driver's
parser to break. It was found that the command breaking could be
replaced by another, already used command, which also retrieves
filesystem information, and it is preferred, so previous command
has been replaced.

Additionally, administrator may not want to automatically mount
an unmounted filesystem in DHSS=False mode, which may be unmounted
for maintenance, so changed behavior to not mount automatically.

Change-Id: I69e7a51ed4485783868c44e58b93bc69b58c8ac2
Closes-bug: #1571000
This commit is contained in:
Rodrigo Barbieri 2016-04-15 16:57:51 -03:00
parent 85e930bca5
commit 0d6de50888
5 changed files with 54 additions and 146 deletions

View File

@ -479,10 +479,10 @@ class HDSHNASDriver(driver.ShareDriver):
LOG.exception(msg)
def _check_fs_mounted(self):
if not self.hnas.check_fs_mounted():
LOG.debug("Filesystem %(fs)s is unmounted. Mounting...",
{'fs': self.fs_name})
self.hnas.mount()
mounted = self.hnas.check_fs_mounted()
if not mounted:
msg = _("Filesystem %s is not mounted.") % self.fs_name
raise exception.HNASBackendException(msg=msg)
def _ensure_share(self, share_id):
"""Ensure that share is exported.

View File

@ -58,11 +58,9 @@ class HNASSSHBackend(object):
output, err = self._execute(command)
line = output.split('\n')
fs_capacity = Capacity(line[3])
available_space = fs_capacity.size - fs_capacity.used
return fs_capacity.size, available_space
fs = Filesystem(line[3])
available_space = fs.size - fs.used
return fs.size, available_space
def nfs_export_add(self, share_id):
path = '/shares/' + share_id
@ -195,16 +193,16 @@ class HNASSSHBackend(object):
self._locked_selectfs('delete', path)
def check_fs_mounted(self):
fs_list = self._get_filesystem_list()
for i in range(0, len(fs_list)):
if fs_list[i].name == self.fs_name:
if fs_list[i].state == 'Mount':
return True
else:
return False
msg = (_("Filesystem %s does not exist or it is not available "
"in the current EVS context.") % self.fs_name)
raise exception.HNASItemNotFoundException(msg=msg)
command = ['df', '-a', '-f', self.fs_name]
output, err = self._execute(command)
if "not found" in output:
msg = (_("Filesystem %s does not exist or it is not available "
"in the current EVS context.") % self.fs_name)
raise exception.HNASItemNotFoundException(msg=msg)
else:
line = output.split('\n')
fs = Filesystem(line[3])
return fs.mounted
def mount(self):
command = ['mount', self.fs_name]
@ -335,29 +333,6 @@ class HNASSSHBackend(object):
export_list.append(Export(items[i]))
return export_list
def _get_filesystem_list(self):
command = ['filesystem-list', self.fs_name]
output, err = self._execute(command)
items = output.split('\n')
filesystem_list = []
fs_name = None
if len(items) > 2:
j = 0
for i in range(2, len(items) - 1):
if "Filesystem " in items[i] and len(items[i].split()) == 2:
description, fs_name = items[i].split()
fs_name = fs_name[:len(fs_name) - 1]
elif "NoEVS" not in items[i]:
# Not considering FS without EVS
filesystem_list.append(FileSystem(items[i]))
if fs_name is not None:
filesystem_list[j].name = fs_name
fs_name = None
j += 1
else:
LOG.debug("Ignoring filesystems without EVS.")
return filesystem_list
@mutils.retry(exception=exception.HNASConnException, wait_random=True)
def _execute(self, commands):
command = ['ssc', '127.0.0.1']
@ -428,24 +403,6 @@ class HNASSSHBackend(object):
raise e
class FileSystem(object):
def __init__(self, data):
if data:
items = data.split()
if len(items) >= 7:
self.name = items[0]
self.dev = items[1]
self.on_span = items[2]
self.state = items[3]
self.evs = int(items[4])
self.capacity = int(items[5])
self.confined = int(items[6])
if len(items) == 8:
self.flag = items[7]
else:
self.flag = ''
class Export(object):
def __init__(self, data):
if data:
@ -533,7 +490,7 @@ class JobSubmit(object):
self.job_id = split_data[8]
class Capacity(object):
class Filesystem(object):
def __init__(self, data):
if data:
items = data.split()
@ -544,10 +501,14 @@ class Capacity(object):
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
if items[5:7] == ["Not", "mounted"]:
self.mounted = False
else:
self.mounted = True
self.used = float(items[5])
self.used_measure = items[6]
if self.used_measure == 'TB':
self.used = self.used * units.Ki
class Quota(object):

View File

@ -101,7 +101,7 @@ class HDSHNASTestCase(test.TestCase):
CONF.hds_hnas_ip_port = 'hds_hnas_ip_port'
CONF.hds_hnas_user = 'hds_hnas_user'
CONF.hds_hnas_password = 'hds_hnas_password'
CONF.hds_hnas_file_system = 'file_system'
CONF.hds_hnas_file_system_name = 'file_system'
CONF.hds_hnas_ssh_private_key = 'private_key'
CONF.hds_hnas_cluster_admin_ip0 = None
CONF.hds_hnas_stalled_job_timeout = 10
@ -498,13 +498,11 @@ class HDSHNASTestCase(test.TestCase):
def test__check_fs_mounted_not_mounted(self):
self.mock_object(ssh.HNASSSHBackend, 'check_fs_mounted', mock.Mock(
return_value=False))
self.mock_object(ssh.HNASSSHBackend, 'mount', mock.Mock())
self._driver._check_fs_mounted()
self.assertRaises(
exception.HNASBackendException, self._driver._check_fs_mounted)
ssh.HNASSSHBackend.check_fs_mounted.assert_called_once_with()
ssh.HNASSSHBackend.mount.assert_called_once_with()
self.assertTrue(self.mock_log.debug.called)
def test__update_share_stats(self):
fake_data = {

View File

@ -58,27 +58,6 @@ Warning: Clearing dangling space trackers from empty vivol"""
HNAS_RESULT_selectfs = "Current selected file system: fake_fs, number(1)"
HNAS_RESULT_fs = """ \
Instance name Dev On span State EVS Cap/GiB Confined Flag
----------------- ---- ------- ------ --- ------- -------- ----
Filesystem 8e6e2c85-fake-long-filesystem-b9b4-e4b09993841e:
8e6e2c8..9993841e 1057 fake_span Mount 2 4 3
fake_fs 1051 fake_span NoEVS - 100 1024
file_system 1055 fake_span Mount 2 4 5 1
"""
HNAS_RESULT_u_fs = """ \
Instance name Dev On span State EVS Cap/GiB Confined Flag
----------------- ---- ------- ------ --- ------- -------- ----
file_system 1055 fake_span Umount 2 4 5
file_system2 1050 fake_span2 NoEVS - 10 0 1
fake_fs 1051 fake_span Umount 2 100 1024 """
HNAS_RESULT_one_fs = """ \
Instance name Dev On span State EVS Cap/GiB Confined Flag
----------------- ---- ------- ------ --- ------- -------- ----
fake_fs 1051 fake_span Mount 2 100 1024 1"""
HNAS_RESULT_expadd = "NFS Export Add: Export added successfully"
HNAS_RESULT_vvol = """vvol_test
@ -261,36 +240,6 @@ Export Modify: Export modified successfully"""
HNAS_RESULT_expnotmod = "Export not modified."
HNAS_RESULT_fslimits = """
Filesystem fake_fs on span fake_span:
Current capacity 100GiB
Thin provision: disabled
Free space on span allows expansion to: 10GiB (Run 'span-expand')
Filesystem is confined to: 1024GiB (Run 'filesystem-confine')
Chunk size allows growth to: 1024GiB (This is a conservative \
estimate)
Largest filesystem that can be checked: 10000GiB (This is a hard limit)
This server model allows growth to: 10000GiB (Upgrade the server)
"""
HNAS_RESULT_fslimits_tb = """ \
Filesystem fake_fs on span fake_span:
Current capacity 1500GiB
Thin provision: disabled
Free space on span allows expansion to: 1000GiB (Run 'span-expand')
Filesystem is confined to: 10240GiB (Run 'filesystem-confine')
Chunk size allows growth to: 10240GiB (This is a conservative \
estimate)
Largest filesystem that can be checked: 10000GiB (This is a hard limit)
This server model allows growth to: 10000GiB (Upgrade the server)
"""
HNAS_RESULT_job = """tree-operation-job-submit: Request submitted successfully.
tree-operation-job-submit: Job id = d933100a-b5f6-11d0-91d9-836896aada5d"""
@ -340,9 +289,6 @@ HNAS_RESULT_tree_job_status_fail = """JOB ID : d933100a-b5f6-11d0-91d9-836896aad
Skipping details : 104 symlinks, 452 hard links,
47 block special devices, 25 character devices"""
HNAS_RESULT_job = """tree-operation-job-submit: Request submitted successfully.
tree-operation-job-submit: Job id = d933100a-b5f6-11d0-91d9-836896aada5d """
HNAS_RESULT_job_completed = """JOB ID : ab4211b8-aac8-11ce-91af-39e0822ea368
Job request
Physical node : 1
@ -417,6 +363,17 @@ HNAS_RESULT_df_tb = """
18.3 GB (25%) No 4 KB,WFS-2,128 DSBs
"""
HNAS_RESULT_df_unmounted = """
ID Label EVS Size Used Snapshots Deduped \
Avail Thin ThinSize ThinAvail FS Type
---- ------------- --- -------- -------------- --------- ------- \
------------- ---- -------- --------- -------------------
1051 FS-ManilaDev1 3 70.00 GB Not mounted 0 B (0%) NA \
18.3 GB (25%) No 4 KB,WFS-2,128 DSBs
"""
HNAS_RESULT_df_error = """File system file_system not found"""
HNAS_RESULT_mounted_filesystem = """
file_system 1055 fake_span Mount 2 4 5 1
"""
@ -650,22 +607,22 @@ class HNASSSHTestCase(test.TestCase):
*locked_selectfs_args)
def test_check_fs_mounted_true(self):
self.mock_object(ssh.HNASSSHBackend, "_get_filesystem_list",
mock.Mock(return_value=[ssh.FileSystem(
HNAS_RESULT_mounted_filesystem)]))
self.mock_object(ssh.HNASSSHBackend, "_execute",
mock.Mock(return_value=(HNAS_RESULT_df, '')))
self.assertTrue(self._driver_ssh.check_fs_mounted())
def test_check_fs_mounted_false(self):
self.mock_object(ssh.HNASSSHBackend, "_get_filesystem_list",
mock.Mock(return_value=[ssh.FileSystem(
HNAS_RESULT_unmounted_filesystem)]))
self.mock_object(
ssh.HNASSSHBackend, "_execute",
mock.Mock(return_value=(HNAS_RESULT_df_unmounted, '')))
self.assertFalse(self._driver_ssh.check_fs_mounted())
def test_check_fs_mounted_eror(self):
self.mock_object(ssh.HNASSSHBackend, "_get_filesystem_list",
mock.Mock(return_value=[]))
def test_check_fs_mounted_error(self):
self.mock_object(
ssh.HNASSSHBackend, "_execute",
mock.Mock(return_value=(HNAS_RESULT_df_error, '')))
self.assertRaises(exception.HNASItemNotFoundException,
self._driver_ssh.check_fs_mounted)
@ -853,19 +810,6 @@ class HNASSSHTestCase(test.TestCase):
self.assertRaises(putils.ProcessExecutionError,
self._driver_ssh._get_share_export, 'fake_id')
def test__get_filesystem_list(self):
self.mock_object(ssh.HNASSSHBackend, '_execute',
mock.Mock(return_value=[HNAS_RESULT_fs, '']))
out = self._driver_ssh._get_filesystem_list()
self.assertEqual('8e6e2c85-fake-long-filesystem-b9b4-e4b09993841e',
out[0].name)
self.assertEqual('fake_span', out[0].on_span)
self.assertEqual('Mount', out[0].state)
self.assertEqual(2, out[0].evs)
self.assertTrue(self.mock_log.debug.called)
def test__execute(self):
key = self.ssh_private_key
commands = ['tree-clone-job-submit', '-e', '/src', '/dst']

View File

@ -0,0 +1,5 @@
---
fixes:
- Crash when using unconfined filesystems in HDS HNAS driver using
SSH backend.
- HDS HNAS Driver no longer mounts unmounted filesystems automatically.