CIFS extension failing because of volume in use

Unmouting of the volume from service instance sometimes fails because
Windows clients tends to check the availability of shares even if not
mounted and the volume is in use then.

Fix finds out processes via smbstatus and kill them before unmounting.

Closes-Bug: 1703581
Change-Id: I2cbf959d7cb849d3ead1655b1a0932fd428a9e9f
Signed-off-by: Goutham Pacha Ravi <gouthampravi@gmail.com>
(cherry picked from commit 2c9fbc7505)
This commit is contained in:
Jan Vondra 2017-08-28 14:57:35 +02:00 committed by Goutham Pacha Ravi
parent b4cd3e596d
commit 95d251e38b
3 changed files with 57 additions and 1 deletions

View File

@ -529,6 +529,30 @@ class CIFSHelperIPAccess(CIFSHelperBase):
]
self._ssh_exec(server, backup_exports)
self._set_allow_hosts(server, [], share_name)
self._kick_out_users(server, share_name)
def _kick_out_users(self, server, share_name):
"""Kick out all users of share"""
(out, _) = self._ssh_exec(server, ['sudo', 'smbstatus', '-S'])
shares = []
header = True
regexp = r"^(?P<share>[^ ]+)\s+(?P<pid>[0-9]+)\s+(?P<machine>[^ ]+).*"
for line in out.splitlines():
line = line.strip()
if not header and line:
match = re.match(regexp, line)
if match:
shares.append(match.groupdict())
else:
raise exception.ShareBackendException(
msg="Failed to obtain smbstatus for %s!" % share_name)
elif line.startswith('----'):
header = False
to_kill = [s['pid'] for s in shares if
share_name == s['share'] or share_name is None]
if to_kill:
self._ssh_exec(server, ['sudo', 'kill', '-15'] + to_kill)
def restore_access_after_maintenance(self, server, share_name):
maintenance_file = self._get_maintenance_file_path(share_name)

View File

@ -678,11 +678,39 @@ class CIFSHelperIPAccessTestCase(test.TestCase):
self.server_details, self.share_name)
self._helper._set_allow_hosts.assert_called_once_with(
self.server_details, [], self.share_name)
kickoff_user_cmd = ['sudo', 'smbstatus', '-S']
self._helper._ssh_exec.assert_any_call(
self.server_details, kickoff_user_cmd)
valid_cmd = ['echo', "'test test2'", '|', 'sudo', 'tee',
maintenance_path]
self._helper._ssh_exec.assert_called_once_with(
self._helper._ssh_exec.assert_any_call(
self.server_details, valid_cmd)
def test__kick_out_users_success(self):
smbstatus_return = """Service pid machine Connected at
-------------------------------------------------------
fake_share_name 1001 fake_machine1 Thu Sep 14 14:59:07 2017
fake_share_name 1002 fake_machine2 Thu Sep 14 14:59:07 2017
"""
self.mock_object(self._helper, '_ssh_exec', mock.Mock(
side_effect=[(smbstatus_return, "fake_stderr"), ("fake", "fake")]))
self._helper._kick_out_users(self.server_details, self.share_name)
self._helper._ssh_exec.assert_any_call(
self.server_details, ['sudo', 'smbstatus', '-S'])
self._helper._ssh_exec.assert_any_call(
self.server_details, ["sudo", "kill", "-15", "1001", "1002"])
def test__kick_out_users_failed(self):
smbstatus_return = """Service pid machine Connected at
-------------------------------------------------------
fake line
"""
self.mock_object(self._helper, '_ssh_exec', mock.Mock(
return_value=(smbstatus_return, "fake_stderr")))
self.assertRaises(exception.ShareBackendException,
self._helper._kick_out_users, self.server_details,
self.share_name)
def test_restore_access_after_maintenance(self):
fake_maintenance_path = "test.path"
self.mock_object(self._helper, '_set_allow_hosts')

View File

@ -0,0 +1,4 @@
---
fixes:
- Fixed the Generic driver to evict and kill any user processes accessing
a share before attempting to extend or shrink a CIFS share.