Skip to content

Commit

Permalink
CA-255945: fix race on mkdir
Browse files Browse the repository at this point in the history
Signed-off-by: Stefano Panella <stefano.panella@citrix.com>
Reviewed-by: Germano Percossi <germano.percossi@citrix.com>
  • Loading branch information
stefanopanella authored and MarkSymsCtx committed Jan 29, 2018
1 parent e561a0b commit 19aad26
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 3 deletions.
8 changes: 7 additions & 1 deletion drivers/mpath_dmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import scsiutil
import mpp_luncheck
import wwid_conf
import errno

iscsi_mpath_file = "/etc/iscsi/iscsid-mpath.conf"
iscsi_default_file = "/etc/iscsi/iscsid-default.conf"
Expand Down Expand Up @@ -55,8 +56,13 @@ def _is_mpp_daemon_running():
return False

def activate_MPdev(sid, dst):
if not os.path.exists(MP_INUSEDIR):
try:
os.mkdir(MP_INUSEDIR)
except OSError as exc:
if exc.errno == errno.EEXIST:
pass
else:
raise
if (mpp_luncheck.is_RdacLun(sid)):
suffix = get_TargetID_LunNUM(sid)
sid_with_suffix = sid + "-" + suffix
Expand Down
49 changes: 47 additions & 2 deletions tests/test_mpath_dmp.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
import mock
"""
Unit tests for mpath dmp
"""
import errno
import os
import unittest
import mock
import testlib
import mpath_dmp
import SR


class Test_mpath_dmp(unittest.TestCase):
# pylint: disable=W0613; mocks don't need to be accessed
# pylint: disable=R0201; methods must be instance for nose to work
# pylint: disable=W0212; unit tests are permitted to snoop
class TestMpathDmp(unittest.TestCase):
"""
Unit tests for mpath dmp
"""

@testlib.with_context
@mock.patch('mpath_dmp.util', autospec=True)
Expand Down Expand Up @@ -38,3 +49,37 @@ def test_is_valid_multipath_device(self, context, util_mod):
# Test when everything is fine
util_mod.doexec.side_effect = [(0, "out", "err"), (0, "out", "err")]
self.assertTrue(mpath_dmp._is_valid_multipath_device("fake_dev"))

@mock.patch('mpath_dmp.mpp_luncheck.is_RdacLun', autospec=True)
@mock.patch('util.pread2', autospec=True)
@mock.patch('mpath_dmp.os.mkdir', autospec=True)
def test_activate_no_exception(self, mock_mkdir, pread2, is_rdaclun):
"""
Test that activeate MPDev works if directory does not exist
"""
is_rdaclun.return_value = False
mpath_dmp.activate_MPdev("sid", "dst")
pread2.assert_called_with(['ln', '-sf', "dst", os.path.join(mpath_dmp.MP_INUSEDIR, "sid")])

@mock.patch('mpath_dmp.mpp_luncheck.is_RdacLun', autospec=True)
@mock.patch('util.pread2', autospec=True)
@mock.patch('mpath_dmp.os.mkdir', autospec=True)
def test_activate_exists_success(self, mock_mkdir, pread2, is_rdaclun):
"""
Test that activeate MPDev works if directory exists
"""
mock_mkdir.side_effect = [OSError(errno.EEXIST, "Directory exists")]
is_rdaclun.return_value = False
mpath_dmp.activate_MPdev("sid", "dst")
pread2.assert_called_with(['ln', '-sf', "dst", os.path.join(mpath_dmp.MP_INUSEDIR, "sid")])

@mock.patch('mpath_dmp.os.mkdir', autospec=True)
def test_activate_permission_denied(self, mock_mkdir):
"""
Test that activeate MPDev works if mkdir returns permission denied
"""
mock_mkdir.side_effect = [OSError(errno.EPERM, "Permission denied")]
with self.assertRaises(OSError) as context:
mpath_dmp.activate_MPdev("sid", "dst")

self.assertEqual(errno.EPERM, context.exception.errno)

0 comments on commit 19aad26

Please sign in to comment.