summaryrefslogtreecommitdiffstats
path: root/test/unit/common/test_fs_utils.py
diff options
context:
space:
mode:
authorPrashanth Pai <ppai@redhat.com>2013-10-30 16:13:50 +0530
committerLuis Pabon <lpabon@redhat.com>2013-11-15 09:06:21 -0800
commitc6d7ddc4bcdefbe7e30946c5c7eb26e74ad0ff0e (patch)
treea6d78410d90a460acfe910e76f5bc529fd6c9031 /test/unit/common/test_fs_utils.py
parentf54e06b612a6fdf04827ae32503dac5a7da5eb4e (diff)
Improve logging and raising DiskFileNoSpace
This commit only improves logging whenever ENOSPC (No space on disk) or EDQUOT (Quota limit exceeded) is returned by glusterfs Also, added methods to: - get filename from file descriptor - log with rate limit Caveat: Although raising DiskFileNoSpace results in object-server returning HTTPInsufficientStorage[507] correctly, the swift proxy-server invokes "best_response" method that returns [503] to the user. When write-behind translator is turned on in glusterfs, it may set errno to EIO instead of ENOSPC/EDQUOT. This is documented in BZ 986812 BUG: 985862, 985253, 1020724 Change-Id: Ib0c5e41c11a8cdccc2077f71c31d8a23229452bb Signed-off-by: Prashanth Pai <ppai@redhat.com> Reviewed-on: http://review.gluster.org/6199 Reviewed-by: Luis Pabon <lpabon@redhat.com> Tested-by: Luis Pabon <lpabon@redhat.com> Reviewed-on: http://review.gluster.org/6269
Diffstat (limited to 'test/unit/common/test_fs_utils.py')
-rw-r--r--test/unit/common/test_fs_utils.py127
1 files changed, 126 insertions, 1 deletions
diff --git a/test/unit/common/test_fs_utils.py b/test/unit/common/test_fs_utils.py
index c7f969e..98f8620 100644
--- a/test/unit/common/test_fs_utils.py
+++ b/test/unit/common/test_fs_utils.py
@@ -20,12 +20,14 @@ import errno
import unittest
import eventlet
from nose import SkipTest
-from mock import patch
+from mock import patch, Mock
+from time import sleep
from tempfile import mkdtemp, mkstemp
from gluster.swift.common import fs_utils as fs
from gluster.swift.common.exceptions import NotDirectoryError, \
FileOrDirNotFoundError, GlusterFileSystemOSError, \
GlusterFileSystemIOError
+from swift.common.exceptions import DiskFileNoSpace
def mock_os_fsync(fd):
return True
@@ -33,6 +35,12 @@ def mock_os_fsync(fd):
def mock_os_fdatasync(fd):
return True
+def mock_os_mkdir_makedirs_enospc(path):
+ raise OSError(errno.ENOSPC, os.strerror(errno.ENOSPC))
+
+def mock_os_mkdir_makedirs_edquot(path):
+ raise OSError(errno.EDQUOT, os.strerror(errno.EDQUOT))
+
class TestFsUtils(unittest.TestCase):
""" Tests for common.fs_utils """
@@ -235,6 +243,30 @@ class TestFsUtils(unittest.TestCase):
os.close(fd)
os.remove(tmpfile)
+ def test_do_write_DiskFileNoSpace(self):
+
+ def mock_os_write_enospc(fd, msg):
+ raise OSError(errno.ENOSPC, os.strerror(errno.ENOSPC))
+
+ def mock_os_write_edquot(fd, msg):
+ raise OSError(errno.EDQUOT, os.strerror(errno.EDQUOT))
+
+ with patch('os.write', mock_os_write_enospc):
+ try:
+ fs.do_write(9, "blah")
+ except DiskFileNoSpace:
+ pass
+ else:
+ self.fail("Expected DiskFileNoSpace exception")
+
+ with patch('os.write', mock_os_write_edquot):
+ try:
+ fs.do_write(9, "blah")
+ except DiskFileNoSpace:
+ pass
+ else:
+ self.fail("Expected DiskFileNoSpace exception")
+
def test_mkdirs(self):
try:
subdir = os.path.join('/tmp', str(random.random()))
@@ -293,6 +325,25 @@ class TestFsUtils(unittest.TestCase):
os.close(fd)
shutil.rmtree(tmpdir)
+ def test_mkdirs_DiskFileNoSpace(self):
+
+ with patch('os.makedirs', mock_os_mkdir_makedirs_enospc):
+ try:
+ fs.mkdirs("blah")
+ except DiskFileNoSpace:
+ pass
+ else:
+ self.fail("Expected DiskFileNoSpace exception")
+
+ with patch('os.makedirs', mock_os_mkdir_makedirs_edquot):
+ try:
+ fs.mkdirs("blah")
+ except DiskFileNoSpace:
+ pass
+ else:
+ self.fail("Expected DiskFileNoSpace exception")
+
+
def test_do_mkdir(self):
try:
path = os.path.join('/tmp', str(random.random()))
@@ -311,6 +362,23 @@ class TestFsUtils(unittest.TestCase):
else:
self.fail("GlusterFileSystemOSError expected")
+ with patch('os.mkdir', mock_os_mkdir_makedirs_enospc):
+ try:
+ fs.do_mkdir("blah")
+ except DiskFileNoSpace:
+ pass
+ else:
+ self.fail("Expected DiskFileNoSpace exception")
+
+ with patch('os.mkdir', mock_os_mkdir_makedirs_edquot):
+ try:
+ fs.do_mkdir("blah")
+ except DiskFileNoSpace:
+ pass
+ else:
+ self.fail("Expected DiskFileNoSpace exception")
+
+
def test_do_listdir(self):
tmpdir = mkdtemp()
try:
@@ -712,3 +780,60 @@ class TestFsUtils(unittest.TestCase):
self.fail("Expected GlusterFileSystemOSError")
finally:
shutil.rmtree(tmpdir)
+
+ def test_get_filename_from_fd(self):
+ tmpdir = mkdtemp()
+ try:
+ fd, tmpfile = mkstemp(dir=tmpdir)
+ result = fs.get_filename_from_fd(fd)
+ self.assertEqual(tmpfile, result)
+ result = fs.get_filename_from_fd(fd, True)
+ self.assertEqual(tmpfile, result)
+ finally:
+ shutil.rmtree(tmpdir)
+
+ def test_get_filename_from_fd_err(self):
+ result = fs.get_filename_from_fd("blah")
+ self.assertIsNone(result)
+ result = fs.get_filename_from_fd(-1000)
+ self.assertIsNone(result)
+ result = fs.get_filename_from_fd("blah", True)
+ self.assertIsNone(result)
+
+ def test_static_var(self):
+ @fs.static_var("counter", 0)
+ def test_func():
+ test_func.counter += 1
+ return test_func.counter
+
+ result = test_func()
+ self.assertEqual(result, 1)
+
+ def test_do_log_rl(self):
+ _mock = Mock()
+ pid = os.getpid()
+ with patch("logging.error", _mock):
+ # The first call always invokes logging.error
+ fs.do_log_rl("Hello %s", "world")
+ _mock.reset_mock()
+ # We call do_log_rl 3 times. Twice in immediate succession and
+ # then after an interval of 1.1 second. Thus, the last call will
+ # invoke logging.error
+ for i in range(2):
+ fs.do_log_rl("Hello %s", "world")
+ sleep(1.1)
+ fs.do_log_rl("Hello %s", "world")
+
+ # We check if logging.error was called exactly once even though
+ # do_log_rl was called 3 times.
+ _mock.assert_called_once_with('[PID:' + str(pid) + '][RateLimitedLog;'
+ 'Count:3] Hello %s', 'world')
+
+ def test_do_log_rl_err(self):
+ _mock = Mock()
+ pid = os.getpid()
+ sleep(1.1)
+ with patch("logging.error", _mock):
+ fs.do_log_rl("Hello %s", "world", log_level="blah")
+ _mock.assert_called_once_with('[PID:' + str(pid) + '][RateLimitedLog;'
+ 'Count:1] Hello %s', 'world')