Remove extra lstat() calls from check_mount
The os.path.exists call performs an lstat, but os.path.ismount already performs the same check. However, it performs a separate lstat() call to check for a symlink, which we remove as well, cutting the number performed in half. Sample program to be straced for comparison: from swift.common.constraints import check_mount import os os.write(1, "Starting\n") if check_mount("/", "tmp"): os.write(1, "Mounted\n") Here is the output of a check on a mounted file system (common case) using the new method: ---- strace new ---- write(1, "Starting\n", 9) = 9 lstat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=8460, ...}) = 0 lstat("/tmp/..", {st_mode=S_IFDIR|0555, st_size=4096, ...}) = 0 write(1, "Mounted\n", 8) = 8 ---- strace old ---- write(1, "Starting\n", 9) = 9 stat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=8460, ...}) = 0 lstat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=8460, ...}) = 0 lstat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=8460, ...}) = 0 lstat("/tmp/..", {st_mode=S_IFDIR|0555, st_size=4096, ...}) = 0 write(1, "Mounted\n", 8) = 8 Change-Id: I027c862a2b7d9ff99d7f61bd43ccc0825dba525c Signed-off-by: Peter Portante <peter.portante@redhat.com>
This commit is contained in:
parent
0fdad0d9d9
commit
e0535f9bf3
@ -17,6 +17,7 @@ import os
|
|||||||
import urllib
|
import urllib
|
||||||
from ConfigParser import ConfigParser, NoSectionError, NoOptionError
|
from ConfigParser import ConfigParser, NoSectionError, NoOptionError
|
||||||
|
|
||||||
|
from swift.common.utils import ismount
|
||||||
from swift.common.swob import HTTPBadRequest, HTTPLengthRequired, \
|
from swift.common.swob import HTTPBadRequest, HTTPLengthRequired, \
|
||||||
HTTPRequestEntityTooLarge
|
HTTPRequestEntityTooLarge
|
||||||
|
|
||||||
@ -169,7 +170,7 @@ def check_mount(root, drive):
|
|||||||
if not (urllib.quote_plus(drive) == drive):
|
if not (urllib.quote_plus(drive) == drive):
|
||||||
return False
|
return False
|
||||||
path = os.path.join(root, drive)
|
path = os.path.join(root, drive)
|
||||||
return os.path.exists(path) and os.path.ismount(path)
|
return ismount(path)
|
||||||
|
|
||||||
|
|
||||||
def check_float(string):
|
def check_float(string):
|
||||||
|
@ -45,6 +45,7 @@ import cPickle as pickle
|
|||||||
import glob
|
import glob
|
||||||
from urlparse import urlparse as stdlib_urlparse, ParseResult
|
from urlparse import urlparse as stdlib_urlparse, ParseResult
|
||||||
import itertools
|
import itertools
|
||||||
|
import stat
|
||||||
|
|
||||||
import eventlet
|
import eventlet
|
||||||
import eventlet.semaphore
|
import eventlet.semaphore
|
||||||
@ -2174,3 +2175,38 @@ class ThreadPool(object):
|
|||||||
return self._run_in_eventlet_tpool(func, *args, **kwargs)
|
return self._run_in_eventlet_tpool(func, *args, **kwargs)
|
||||||
else:
|
else:
|
||||||
return self.run_in_thread(func, *args, **kwargs)
|
return self.run_in_thread(func, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def ismount(path):
|
||||||
|
"""
|
||||||
|
Test whether a path is a mount point.
|
||||||
|
|
||||||
|
This is code hijacked from C Python 2.6.8, adapted to remove the extra
|
||||||
|
lstat() system call.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
s1 = os.lstat(path)
|
||||||
|
except os.error as err:
|
||||||
|
if err.errno == errno.ENOENT:
|
||||||
|
# It doesn't exist -- so not a mount point :-)
|
||||||
|
return False
|
||||||
|
raise
|
||||||
|
|
||||||
|
if stat.S_ISLNK(s1.st_mode):
|
||||||
|
# A symlink can never be a mount point
|
||||||
|
return False
|
||||||
|
|
||||||
|
s2 = os.lstat(os.path.join(path, '..'))
|
||||||
|
dev1 = s1.st_dev
|
||||||
|
dev2 = s2.st_dev
|
||||||
|
if dev1 != dev2:
|
||||||
|
# path/.. on a different device as path
|
||||||
|
return True
|
||||||
|
|
||||||
|
ino1 = s1.st_ino
|
||||||
|
ino2 = s2.st_ino
|
||||||
|
if ino1 == ino2:
|
||||||
|
# path/.. is the same i-node as path
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
@ -18,6 +18,7 @@ from unittest import TestCase
|
|||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from posix import stat_result, statvfs_result
|
from posix import stat_result, statvfs_result
|
||||||
import os
|
import os
|
||||||
|
import mock
|
||||||
|
|
||||||
import swift.common.constraints
|
import swift.common.constraints
|
||||||
from swift import __version__ as swiftver
|
from swift import __version__ as swiftver
|
||||||
@ -30,9 +31,11 @@ class FakeApp(object):
|
|||||||
def __call__(self, env, start_response):
|
def __call__(self, env, start_response):
|
||||||
return "FAKE APP"
|
return "FAKE APP"
|
||||||
|
|
||||||
|
|
||||||
def start_response(*args):
|
def start_response(*args):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class FakeFromCache(object):
|
class FakeFromCache(object):
|
||||||
|
|
||||||
def __init__(self, out=None):
|
def __init__(self, out=None):
|
||||||
@ -43,6 +46,7 @@ class FakeFromCache(object):
|
|||||||
self.fakeout_calls.append((args, kwargs))
|
self.fakeout_calls.append((args, kwargs))
|
||||||
return self.fakeout
|
return self.fakeout
|
||||||
|
|
||||||
|
|
||||||
class OpenAndReadTester(object):
|
class OpenAndReadTester(object):
|
||||||
|
|
||||||
def __init__(self, output_iter):
|
def __init__(self, output_iter):
|
||||||
@ -76,35 +80,29 @@ class OpenAndReadTester(object):
|
|||||||
self.open_calls.append((args, kwargs))
|
self.open_calls.append((args, kwargs))
|
||||||
yield self
|
yield self
|
||||||
|
|
||||||
|
|
||||||
class MockOS(object):
|
class MockOS(object):
|
||||||
|
|
||||||
def __init__(self, ls_out=None, pe_out=None, statvfs_out=None,
|
def __init__(self, ls_out=None, im_out=False, statvfs_out=None):
|
||||||
lstat_out=(1, 1, 5, 4, 5, 5, 55, 55, 55, 55)):
|
|
||||||
self.ls_output = ls_out
|
self.ls_output = ls_out
|
||||||
self.path_exists_output = pe_out
|
self.ismount_output = im_out
|
||||||
self.statvfs_output = statvfs_out
|
self.statvfs_output = statvfs_out
|
||||||
self.lstat_output_tuple = lstat_out
|
|
||||||
self.listdir_calls = []
|
self.listdir_calls = []
|
||||||
self.statvfs_calls = []
|
self.statvfs_calls = []
|
||||||
self.path_exists_calls = []
|
self.ismount_calls = []
|
||||||
self.lstat_calls = []
|
|
||||||
|
|
||||||
def fake_listdir(self, *args, **kwargs):
|
def fake_listdir(self, *args, **kwargs):
|
||||||
self.listdir_calls.append((args, kwargs))
|
self.listdir_calls.append((args, kwargs))
|
||||||
return self.ls_output
|
return self.ls_output
|
||||||
|
|
||||||
def fake_path_exists(self, *args, **kwargs):
|
def fake_ismount(self, *args, **kwargs):
|
||||||
self.path_exists_calls.append((args, kwargs))
|
self.ismount_calls.append((args, kwargs))
|
||||||
return self.path_exists_output
|
return self.ismount_output
|
||||||
|
|
||||||
def fake_statvfs(self, *args, **kwargs):
|
def fake_statvfs(self, *args, **kwargs):
|
||||||
self.statvfs_calls.append((args, kwargs))
|
self.statvfs_calls.append((args, kwargs))
|
||||||
return statvfs_result(self.statvfs_output)
|
return statvfs_result(self.statvfs_output)
|
||||||
|
|
||||||
def fake_lstat(self, *args, **kwargs):
|
|
||||||
self.lstat_calls.append((args, kwargs))
|
|
||||||
return stat_result(self.lstat_output_tuple)
|
|
||||||
|
|
||||||
|
|
||||||
class FakeRecon(object):
|
class FakeRecon(object):
|
||||||
|
|
||||||
@ -175,6 +173,7 @@ class FakeRecon(object):
|
|||||||
def raise_Exception(self, *args, **kwargs):
|
def raise_Exception(self, *args, **kwargs):
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
|
|
||||||
class TestReconSuccess(TestCase):
|
class TestReconSuccess(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -182,12 +181,10 @@ class TestReconSuccess(TestCase):
|
|||||||
self.mockos = MockOS()
|
self.mockos = MockOS()
|
||||||
self.fakecache = FakeFromCache()
|
self.fakecache = FakeFromCache()
|
||||||
self.real_listdir = os.listdir
|
self.real_listdir = os.listdir
|
||||||
self.real_path_exists = os.path.exists
|
self.real_ismount = swift.common.constraints.ismount
|
||||||
self.real_lstat = os.lstat
|
|
||||||
self.real_statvfs = os.statvfs
|
self.real_statvfs = os.statvfs
|
||||||
os.listdir = self.mockos.fake_listdir
|
os.listdir = self.mockos.fake_listdir
|
||||||
os.path.exists = self.mockos.fake_path_exists
|
swift.common.constraints.ismount = self.mockos.fake_ismount
|
||||||
os.lstat = self.mockos.fake_lstat
|
|
||||||
os.statvfs = self.mockos.fake_statvfs
|
os.statvfs = self.mockos.fake_statvfs
|
||||||
self.real_from_cache = self.app._from_recon_cache
|
self.real_from_cache = self.app._from_recon_cache
|
||||||
self.app._from_recon_cache = self.fakecache.fake_from_recon_cache
|
self.app._from_recon_cache = self.fakecache.fake_from_recon_cache
|
||||||
@ -195,8 +192,7 @@ class TestReconSuccess(TestCase):
|
|||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
os.listdir = self.real_listdir
|
os.listdir = self.real_listdir
|
||||||
os.path.exists = self.real_path_exists
|
swift.common.constraints.ismount = self.real_ismount
|
||||||
os.lstat = self.real_lstat
|
|
||||||
os.statvfs = self.real_statvfs
|
os.statvfs = self.real_statvfs
|
||||||
del self.mockos
|
del self.mockos
|
||||||
self.app._from_recon_cache = self.real_from_cache
|
self.app._from_recon_cache = self.real_from_cache
|
||||||
@ -548,17 +544,11 @@ class TestReconSuccess(TestCase):
|
|||||||
|
|
||||||
def test_get_unmounted(self):
|
def test_get_unmounted(self):
|
||||||
|
|
||||||
def fake_checkmount_true(*args):
|
|
||||||
return True
|
|
||||||
|
|
||||||
unmounted_resp = [{'device': 'fakeone', 'mounted': False},
|
unmounted_resp = [{'device': 'fakeone', 'mounted': False},
|
||||||
{'device': 'faketwo', 'mounted': False}]
|
{'device': 'faketwo', 'mounted': False}]
|
||||||
self.mockos.ls_output = ['fakeone', 'faketwo']
|
self.mockos.ls_output = ['fakeone', 'faketwo']
|
||||||
self.mockos.path_exists_output=False
|
self.mockos.ismount_output = False
|
||||||
real_checkmount = swift.common.constraints.check_mount
|
|
||||||
swift.common.constraints.check_mount = fake_checkmount_true
|
|
||||||
rv = self.app.get_unmounted()
|
rv = self.app.get_unmounted()
|
||||||
swift.common.constraints.check_mount = real_checkmount
|
|
||||||
self.assertEquals(self.mockos.listdir_calls, [(('/srv/node/',), {})])
|
self.assertEquals(self.mockos.listdir_calls, [(('/srv/node/',), {})])
|
||||||
self.assertEquals(rv, unmounted_resp)
|
self.assertEquals(rv, unmounted_resp)
|
||||||
|
|
||||||
@ -569,26 +559,24 @@ class TestReconSuccess(TestCase):
|
|||||||
|
|
||||||
unmounted_resp = []
|
unmounted_resp = []
|
||||||
self.mockos.ls_output = []
|
self.mockos.ls_output = []
|
||||||
self.mockos.path_exists_output=False
|
self.mockos.ismount_output = False
|
||||||
real_checkmount = swift.common.constraints.check_mount
|
|
||||||
swift.common.constraints.check_mount = fake_checkmount_true
|
|
||||||
rv = self.app.get_unmounted()
|
rv = self.app.get_unmounted()
|
||||||
swift.common.constraints.check_mount = real_checkmount
|
|
||||||
self.assertEquals(self.mockos.listdir_calls, [(('/srv/node/',), {})])
|
self.assertEquals(self.mockos.listdir_calls, [(('/srv/node/',), {})])
|
||||||
self.assertEquals(rv, unmounted_resp)
|
self.assertEquals(rv, unmounted_resp)
|
||||||
|
|
||||||
def test_get_diskusage(self):
|
def test_get_diskusage(self):
|
||||||
#posix.statvfs_result(f_bsize=4096, f_frsize=4096, f_blocks=1963185,
|
#posix.statvfs_result(f_bsize=4096, f_frsize=4096, f_blocks=1963185,
|
||||||
# f_bfree=1113075, f_bavail=1013351, f_files=498736,
|
# f_bfree=1113075, f_bavail=1013351,
|
||||||
|
# f_files=498736,
|
||||||
# f_ffree=397839, f_favail=397839, f_flag=0,
|
# f_ffree=397839, f_favail=397839, f_flag=0,
|
||||||
# f_namemax=255)
|
# f_namemax=255)
|
||||||
statvfs_content=(4096, 4096, 1963185, 1113075, 1013351, 498736, 397839,
|
statvfs_content = (4096, 4096, 1963185, 1113075, 1013351, 498736,
|
||||||
397839, 0, 255)
|
397839, 397839, 0, 255)
|
||||||
du_resp = [{'device': 'canhazdrive1', 'avail': 4150685696,
|
du_resp = [{'device': 'canhazdrive1', 'avail': 4150685696,
|
||||||
'mounted': True, 'used': 3890520064, 'size': 8041205760}]
|
'mounted': True, 'used': 3890520064, 'size': 8041205760}]
|
||||||
self.mockos.ls_output = ['canhazdrive1']
|
self.mockos.ls_output = ['canhazdrive1']
|
||||||
self.mockos.statvfs_output = statvfs_content
|
self.mockos.statvfs_output = statvfs_content
|
||||||
self.mockos.path_exists_output=True
|
self.mockos.ismount_output = True
|
||||||
rv = self.app.get_diskusage()
|
rv = self.app.get_diskusage()
|
||||||
self.assertEquals(self.mockos.statvfs_calls,
|
self.assertEquals(self.mockos.statvfs_calls,
|
||||||
[(('/srv/node/canhazdrive1',), {})])
|
[(('/srv/node/canhazdrive1',), {})])
|
||||||
@ -598,21 +586,28 @@ class TestReconSuccess(TestCase):
|
|||||||
du_resp = [{'device': 'canhazdrive1', 'avail': '',
|
du_resp = [{'device': 'canhazdrive1', 'avail': '',
|
||||||
'mounted': False, 'used': '', 'size': ''}]
|
'mounted': False, 'used': '', 'size': ''}]
|
||||||
self.mockos.ls_output = ['canhazdrive1']
|
self.mockos.ls_output = ['canhazdrive1']
|
||||||
self.mockos.path_exists_output=False
|
self.mockos.ismount_output = False
|
||||||
rv = self.app.get_diskusage()
|
rv = self.app.get_diskusage()
|
||||||
self.assertEquals(self.mockos.listdir_calls, [(('/srv/node/',), {})])
|
self.assertEquals(self.mockos.listdir_calls, [(('/srv/node/',), {})])
|
||||||
self.assertEquals(self.mockos.path_exists_calls,
|
self.assertEquals(self.mockos.ismount_calls,
|
||||||
[(('/srv/node/canhazdrive1',), {})])
|
[(('/srv/node/canhazdrive1',), {})])
|
||||||
self.assertEquals(rv, du_resp)
|
self.assertEquals(rv, du_resp)
|
||||||
|
|
||||||
def test_get_quarantine_count(self):
|
def test_get_quarantine_count(self):
|
||||||
|
self.mockos.ls_output = ['sda']
|
||||||
|
self.mockos.ismount_output = True
|
||||||
|
|
||||||
|
def fake_lstat(*args, **kwargs):
|
||||||
#posix.lstat_result(st_mode=1, st_ino=2, st_dev=3, st_nlink=4,
|
#posix.lstat_result(st_mode=1, st_ino=2, st_dev=3, st_nlink=4,
|
||||||
# st_uid=5, st_gid=6, st_size=7, st_atime=8,
|
# st_uid=5, st_gid=6, st_size=7, st_atime=8,
|
||||||
# st_mtime=9, st_ctime=10)
|
# st_mtime=9, st_ctime=10)
|
||||||
lstat_content = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
|
return stat_result((1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
|
||||||
self.mockos.ls_output=['sda']
|
|
||||||
self.mockos.path_exists_output=True
|
def fake_exists(*args, **kwargs):
|
||||||
self.mockos.lstat_output=lstat_content
|
return True
|
||||||
|
|
||||||
|
with mock.patch("os.lstat", fake_lstat):
|
||||||
|
with mock.patch("os.path.exists", fake_exists):
|
||||||
rv = self.app.get_quarantine_count()
|
rv = self.app.get_quarantine_count()
|
||||||
self.assertEquals(rv, {'objects': 2, 'accounts': 2, 'containers': 2})
|
self.assertEquals(rv, {'objects': 2, 'accounts': 2, 'containers': 2})
|
||||||
|
|
||||||
@ -627,6 +622,7 @@ class TestReconSuccess(TestCase):
|
|||||||
self.assertEquals(oart.open_calls, [(('/proc/net/sockstat', 'r'), {}),
|
self.assertEquals(oart.open_calls, [(('/proc/net/sockstat', 'r'), {}),
|
||||||
(('/proc/net/sockstat6', 'r'), {})])
|
(('/proc/net/sockstat6', 'r'), {})])
|
||||||
|
|
||||||
|
|
||||||
class TestReconMiddleware(unittest.TestCase):
|
class TestReconMiddleware(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
import mock
|
||||||
|
|
||||||
from test.unit import MockTrue
|
from test.unit import MockTrue
|
||||||
|
|
||||||
from swift.common.swob import HTTPBadRequest, Request
|
from swift.common.swob import HTTPBadRequest, Request
|
||||||
@ -170,14 +172,13 @@ class TestConstraints(unittest.TestCase):
|
|||||||
|
|
||||||
def test_check_mount(self):
|
def test_check_mount(self):
|
||||||
self.assertFalse(constraints.check_mount('', ''))
|
self.assertFalse(constraints.check_mount('', ''))
|
||||||
constraints.os = MockTrue() # mock os module
|
with mock.patch("swift.common.constraints.ismount", MockTrue()):
|
||||||
self.assertTrue(constraints.check_mount('/srv', '1'))
|
self.assertTrue(constraints.check_mount('/srv', '1'))
|
||||||
self.assertTrue(constraints.check_mount('/srv', 'foo-bar'))
|
self.assertTrue(constraints.check_mount('/srv', 'foo-bar'))
|
||||||
self.assertTrue(constraints.check_mount('/srv', '003ed03c-242a-4b2f-bee9-395f801d1699'))
|
self.assertTrue(constraints.check_mount('/srv', '003ed03c-242a-4b2f-bee9-395f801d1699'))
|
||||||
self.assertFalse(constraints.check_mount('/srv', 'foo bar'))
|
self.assertFalse(constraints.check_mount('/srv', 'foo bar'))
|
||||||
self.assertFalse(constraints.check_mount('/srv', 'foo/bar'))
|
self.assertFalse(constraints.check_mount('/srv', 'foo/bar'))
|
||||||
self.assertFalse(constraints.check_mount('/srv', 'foo?bar'))
|
self.assertFalse(constraints.check_mount('/srv', 'foo?bar'))
|
||||||
reload(constraints) # put it back
|
|
||||||
|
|
||||||
def test_check_float(self):
|
def test_check_float(self):
|
||||||
self.assertFalse(constraints.check_float(''))
|
self.assertFalse(constraints.check_float(''))
|
||||||
@ -217,5 +218,6 @@ class TestConstraints(unittest.TestCase):
|
|||||||
self.assertTrue(c.MAX_HEADER_SIZE > c.MAX_META_NAME_LENGTH)
|
self.assertTrue(c.MAX_HEADER_SIZE > c.MAX_META_NAME_LENGTH)
|
||||||
self.assertTrue(c.MAX_HEADER_SIZE > c.MAX_META_VALUE_LENGTH)
|
self.assertTrue(c.MAX_HEADER_SIZE > c.MAX_META_VALUE_LENGTH)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -149,10 +149,10 @@ class TestDatabaseBroker(unittest.TestCase):
|
|||||||
conn.execute('SELECT * FROM outgoing_sync')
|
conn.execute('SELECT * FROM outgoing_sync')
|
||||||
conn.execute('SELECT * FROM incoming_sync')
|
conn.execute('SELECT * FROM incoming_sync')
|
||||||
|
|
||||||
def my_exists(*a, **kw):
|
def my_ismount(*a, **kw):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
with patch('os.path.exists', my_exists):
|
with patch('os.path.ismount', my_ismount):
|
||||||
broker = DatabaseBroker(os.path.join(self.testdir, '1.db'))
|
broker = DatabaseBroker(os.path.join(self.testdir, '1.db'))
|
||||||
broker._initialize = stub
|
broker._initialize = stub
|
||||||
self.assertRaises(swift.common.db.DatabaseAlreadyExists,
|
self.assertRaises(swift.common.db.DatabaseAlreadyExists,
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
from test.unit import temptree
|
from test.unit import temptree
|
||||||
|
|
||||||
import ctypes
|
import ctypes
|
||||||
import errno
|
import errno
|
||||||
import eventlet
|
import eventlet
|
||||||
@ -26,17 +27,21 @@ import random
|
|||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
import fcntl
|
import fcntl
|
||||||
|
import shutil
|
||||||
|
|
||||||
from Queue import Queue, Empty
|
from Queue import Queue, Empty
|
||||||
from getpass import getuser
|
from getpass import getuser
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from tempfile import TemporaryFile, NamedTemporaryFile
|
from tempfile import TemporaryFile, NamedTemporaryFile, mkdtemp
|
||||||
|
|
||||||
from mock import MagicMock, patch
|
from mock import MagicMock, patch
|
||||||
|
|
||||||
@ -335,7 +340,7 @@ class TestUtils(unittest.TestCase):
|
|||||||
lfo.tell()
|
lfo.tell()
|
||||||
|
|
||||||
def test_parse_options(self):
|
def test_parse_options(self):
|
||||||
# use mkstemp to get a file that is definitely on disk
|
# Get a file that is definitely on disk
|
||||||
with NamedTemporaryFile() as f:
|
with NamedTemporaryFile() as f:
|
||||||
conf_file = f.name
|
conf_file = f.name
|
||||||
conf, options = utils.parse_options(test_args=[conf_file])
|
conf, options = utils.parse_options(test_args=[conf_file])
|
||||||
@ -414,9 +419,11 @@ class TestUtils(unittest.TestCase):
|
|||||||
def test_get_logger_sysloghandler_plumbing(self):
|
def test_get_logger_sysloghandler_plumbing(self):
|
||||||
orig_sysloghandler = utils.SysLogHandler
|
orig_sysloghandler = utils.SysLogHandler
|
||||||
syslog_handler_args = []
|
syslog_handler_args = []
|
||||||
|
|
||||||
def syslog_handler_catcher(*args, **kwargs):
|
def syslog_handler_catcher(*args, **kwargs):
|
||||||
syslog_handler_args.append((args, kwargs))
|
syslog_handler_args.append((args, kwargs))
|
||||||
return orig_sysloghandler(*args, **kwargs)
|
return orig_sysloghandler(*args, **kwargs)
|
||||||
|
|
||||||
syslog_handler_catcher.LOG_LOCAL0 = orig_sysloghandler.LOG_LOCAL0
|
syslog_handler_catcher.LOG_LOCAL0 = orig_sysloghandler.LOG_LOCAL0
|
||||||
syslog_handler_catcher.LOG_LOCAL3 = orig_sysloghandler.LOG_LOCAL3
|
syslog_handler_catcher.LOG_LOCAL3 = orig_sysloghandler.LOG_LOCAL3
|
||||||
|
|
||||||
@ -1375,6 +1382,133 @@ log_name = %(yarr)s'''
|
|||||||
|
|
||||||
self.assertRaises(OSError, os.remove, nt.name)
|
self.assertRaises(OSError, os.remove, nt.name)
|
||||||
|
|
||||||
|
def test_ismount_path_does_not_exist(self):
|
||||||
|
tmpdir = mkdtemp()
|
||||||
|
try:
|
||||||
|
assert utils.ismount(os.path.join(tmpdir, 'bar')) is False
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
def test_ismount_path_not_mount(self):
|
||||||
|
tmpdir = mkdtemp()
|
||||||
|
try:
|
||||||
|
assert utils.ismount(tmpdir) is False
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
def test_ismount_path_error(self):
|
||||||
|
|
||||||
|
def _mock_os_lstat(path):
|
||||||
|
raise OSError(13, "foo")
|
||||||
|
|
||||||
|
tmpdir = mkdtemp()
|
||||||
|
try:
|
||||||
|
with patch("os.lstat", _mock_os_lstat):
|
||||||
|
try:
|
||||||
|
utils.ismount(tmpdir)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.fail("Expected OSError")
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
def test_ismount_path_is_symlink(self):
|
||||||
|
tmpdir = mkdtemp()
|
||||||
|
try:
|
||||||
|
link = os.path.join(tmpdir, "tmp")
|
||||||
|
os.symlink("/tmp", link)
|
||||||
|
assert utils.ismount(link) is False
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
def test_ismount_path_is_root(self):
|
||||||
|
assert utils.ismount('/') is True
|
||||||
|
|
||||||
|
def test_ismount_parent_path_error(self):
|
||||||
|
|
||||||
|
_os_lstat = os.lstat
|
||||||
|
|
||||||
|
def _mock_os_lstat(path):
|
||||||
|
if path.endswith(".."):
|
||||||
|
raise OSError(13, "foo")
|
||||||
|
else:
|
||||||
|
return _os_lstat(path)
|
||||||
|
|
||||||
|
tmpdir = mkdtemp()
|
||||||
|
try:
|
||||||
|
with patch("os.lstat", _mock_os_lstat):
|
||||||
|
try:
|
||||||
|
utils.ismount(tmpdir)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.fail("Expected OSError")
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
def test_ismount_successes_dev(self):
|
||||||
|
|
||||||
|
_os_lstat = os.lstat
|
||||||
|
|
||||||
|
class MockStat(object):
|
||||||
|
def __init__(self, mode, dev, ino):
|
||||||
|
self.st_mode = mode
|
||||||
|
self.st_dev = dev
|
||||||
|
self.st_ino = ino
|
||||||
|
|
||||||
|
def _mock_os_lstat(path):
|
||||||
|
if path.endswith(".."):
|
||||||
|
parent = _os_lstat(path)
|
||||||
|
return MockStat(parent.st_mode, parent.st_dev + 1,
|
||||||
|
parent.st_ino)
|
||||||
|
else:
|
||||||
|
return _os_lstat(path)
|
||||||
|
|
||||||
|
tmpdir = mkdtemp()
|
||||||
|
try:
|
||||||
|
with patch("os.lstat", _mock_os_lstat):
|
||||||
|
try:
|
||||||
|
utils.ismount(tmpdir)
|
||||||
|
except OSError:
|
||||||
|
self.fail("Unexpected exception")
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
def test_ismount_successes_ino(self):
|
||||||
|
|
||||||
|
_os_lstat = os.lstat
|
||||||
|
|
||||||
|
class MockStat(object):
|
||||||
|
def __init__(self, mode, dev, ino):
|
||||||
|
self.st_mode = mode
|
||||||
|
self.st_dev = dev
|
||||||
|
self.st_ino = ino
|
||||||
|
|
||||||
|
def _mock_os_lstat(path):
|
||||||
|
if path.endswith(".."):
|
||||||
|
return _os_lstat(path)
|
||||||
|
else:
|
||||||
|
parent_path = os.path.join(path, "..")
|
||||||
|
child = _os_lstat(path)
|
||||||
|
parent = _os_lstat(parent_path)
|
||||||
|
return MockStat(child.st_mode, parent.st_ino,
|
||||||
|
child.st_dev)
|
||||||
|
|
||||||
|
tmpdir = mkdtemp()
|
||||||
|
try:
|
||||||
|
with patch("os.lstat", _mock_os_lstat):
|
||||||
|
try:
|
||||||
|
utils.ismount(tmpdir)
|
||||||
|
except OSError:
|
||||||
|
self.fail("Unexpected exception")
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
|
||||||
class TestFileLikeIter(unittest.TestCase):
|
class TestFileLikeIter(unittest.TestCase):
|
||||||
|
|
||||||
@ -1399,7 +1533,6 @@ class TestFileLikeIter(unittest.TestCase):
|
|||||||
|
|
||||||
def test_read(self):
|
def test_read(self):
|
||||||
in_iter = ['abc', 'de', 'fghijk', 'l']
|
in_iter = ['abc', 'de', 'fghijk', 'l']
|
||||||
chunks = []
|
|
||||||
iter_file = utils.FileLikeIter(in_iter)
|
iter_file = utils.FileLikeIter(in_iter)
|
||||||
self.assertEquals(iter_file.read(), ''.join(in_iter))
|
self.assertEquals(iter_file.read(), ''.join(in_iter))
|
||||||
|
|
||||||
@ -1758,7 +1891,9 @@ class TestAffinityLocalityPredicate(unittest.TestCase):
|
|||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError,
|
||||||
utils.affinity_locality_predicate, 'r1z1=1')
|
utils.affinity_locality_predicate, 'r1z1=1')
|
||||||
|
|
||||||
|
|
||||||
class TestGreenthreadSafeIterator(unittest.TestCase):
|
class TestGreenthreadSafeIterator(unittest.TestCase):
|
||||||
|
|
||||||
def increment(self, iterable):
|
def increment(self, iterable):
|
||||||
plus_ones = []
|
plus_ones = []
|
||||||
for n in iterable:
|
for n in iterable:
|
||||||
@ -1790,6 +1925,7 @@ class TestGreenthreadSafeIterator(unittest.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestStatsdLoggingDelegation(unittest.TestCase):
|
class TestStatsdLoggingDelegation(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
self.sock.bind(('localhost', 0))
|
self.sock.bind(('localhost', 0))
|
||||||
@ -2030,10 +2166,13 @@ class TestStatsdLoggingDelegation(unittest.TestCase):
|
|||||||
|
|
||||||
def test_no_fdatasync(self):
|
def test_no_fdatasync(self):
|
||||||
called = []
|
called = []
|
||||||
|
|
||||||
class NoFdatasync:
|
class NoFdatasync:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def fsync(fd):
|
def fsync(fd):
|
||||||
called.append(fd)
|
called.append(fd)
|
||||||
|
|
||||||
with patch('swift.common.utils.os', NoFdatasync()):
|
with patch('swift.common.utils.os', NoFdatasync()):
|
||||||
with patch('swift.common.utils.fsync', fsync):
|
with patch('swift.common.utils.fsync', fsync):
|
||||||
utils.fdatasync(12345)
|
utils.fdatasync(12345)
|
||||||
@ -2041,38 +2180,52 @@ class TestStatsdLoggingDelegation(unittest.TestCase):
|
|||||||
|
|
||||||
def test_yes_fdatasync(self):
|
def test_yes_fdatasync(self):
|
||||||
called = []
|
called = []
|
||||||
|
|
||||||
class YesFdatasync:
|
class YesFdatasync:
|
||||||
|
|
||||||
def fdatasync(self, fd):
|
def fdatasync(self, fd):
|
||||||
called.append(fd)
|
called.append(fd)
|
||||||
|
|
||||||
with patch('swift.common.utils.os', YesFdatasync()):
|
with patch('swift.common.utils.os', YesFdatasync()):
|
||||||
utils.fdatasync(12345)
|
utils.fdatasync(12345)
|
||||||
self.assertEquals(called, [12345])
|
self.assertEquals(called, [12345])
|
||||||
|
|
||||||
def test_fsync_bad_fullsync(self):
|
def test_fsync_bad_fullsync(self):
|
||||||
|
|
||||||
class FCNTL:
|
class FCNTL:
|
||||||
|
|
||||||
F_FULLSYNC = 123
|
F_FULLSYNC = 123
|
||||||
|
|
||||||
def fcntl(self, fd, op):
|
def fcntl(self, fd, op):
|
||||||
raise IOError(18)
|
raise IOError(18)
|
||||||
|
|
||||||
with patch('swift.common.utils.fcntl', FCNTL()):
|
with patch('swift.common.utils.fcntl', FCNTL()):
|
||||||
self.assertRaises(OSError, lambda: utils.fsync(12345))
|
self.assertRaises(OSError, lambda: utils.fsync(12345))
|
||||||
|
|
||||||
def test_fsync_f_fullsync(self):
|
def test_fsync_f_fullsync(self):
|
||||||
called = []
|
called = []
|
||||||
|
|
||||||
class FCNTL:
|
class FCNTL:
|
||||||
|
|
||||||
F_FULLSYNC = 123
|
F_FULLSYNC = 123
|
||||||
|
|
||||||
def fcntl(self, fd, op):
|
def fcntl(self, fd, op):
|
||||||
called[:] = [fd, op]
|
called[:] = [fd, op]
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
with patch('swift.common.utils.fcntl', FCNTL()):
|
with patch('swift.common.utils.fcntl', FCNTL()):
|
||||||
utils.fsync(12345)
|
utils.fsync(12345)
|
||||||
self.assertEquals(called, [12345, 123])
|
self.assertEquals(called, [12345, 123])
|
||||||
|
|
||||||
def test_fsync_no_fullsync(self):
|
def test_fsync_no_fullsync(self):
|
||||||
called = []
|
called = []
|
||||||
|
|
||||||
class FCNTL:
|
class FCNTL:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def fsync(fd):
|
def fsync(fd):
|
||||||
called.append(fd)
|
called.append(fd)
|
||||||
|
|
||||||
with patch('swift.common.utils.fcntl', FCNTL()):
|
with patch('swift.common.utils.fcntl', FCNTL()):
|
||||||
with patch('os.fsync', fsync):
|
with patch('os.fsync', fsync):
|
||||||
utils.fsync(12345)
|
utils.fsync(12345)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user