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:
parent
85e930bca5
commit
0d6de50888
@ -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.
|
||||
|
@ -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):
|
||||
|
@ -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 = {
|
||||
|
@ -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']
|
||||
|
@ -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.
|
Loading…
Reference in New Issue
Block a user