From b07c2484b6f0d5165d867651fbc123280e7b012d Mon Sep 17 00:00:00 2001 From: Jan Vondra Date: Mon, 28 Aug 2017 14:57:35 +0200 Subject: [PATCH] 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 (cherry picked from commit 2c9fbc75059ac724cd845317473b7df4a8dcdc35) (cherry picked from commit 95d251e38b4b4526c862a428da93f568fe7a23ad) --- manila/share/drivers/helpers.py | 24 +++++++++++++++ manila/tests/share/drivers/test_helpers.py | 30 ++++++++++++++++++- ...use-of-volume-in-use-3fea31c4a58e2f1b.yaml | 4 +++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/bug-1703581-cifs-extension-failing-because-of-volume-in-use-3fea31c4a58e2f1b.yaml diff --git a/manila/share/drivers/helpers.py b/manila/share/drivers/helpers.py index 8ae0468807..9f184f4b14 100644 --- a/manila/share/drivers/helpers.py +++ b/manila/share/drivers/helpers.py @@ -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[^ ]+)\s+(?P[0-9]+)\s+(?P[^ ]+).*" + 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) diff --git a/manila/tests/share/drivers/test_helpers.py b/manila/tests/share/drivers/test_helpers.py index 9894cf4834..a88db6e8d6 100644 --- a/manila/tests/share/drivers/test_helpers.py +++ b/manila/tests/share/drivers/test_helpers.py @@ -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') diff --git a/releasenotes/notes/bug-1703581-cifs-extension-failing-because-of-volume-in-use-3fea31c4a58e2f1b.yaml b/releasenotes/notes/bug-1703581-cifs-extension-failing-because-of-volume-in-use-3fea31c4a58e2f1b.yaml new file mode 100644 index 0000000000..910bf7a2ec --- /dev/null +++ b/releasenotes/notes/bug-1703581-cifs-extension-failing-because-of-volume-in-use-3fea31c4a58e2f1b.yaml @@ -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.