Handle os.listdir failures in container-updater

While investigating bug 1375348 I discovered the problem
reported there was not limited to the object-auditor.  The
container-updated has similar bugs.

This patch catches the unhandled exception that can be thrown by
os.listdir.

Change-Id: I7eed122bf6b663e6e7894ace136b6f4653db4985
Related-bug: 1375348
This commit is contained in:
Jay S. Bryant
2014-10-02 21:13:30 -05:00
parent 702d88bc89
commit d895cea07f
2 changed files with 50 additions and 2 deletions

View File

@@ -70,6 +70,14 @@ class ContainerUpdater(Daemon):
self.account_ring = Ring(self.swift_dir, ring_name='account') self.account_ring = Ring(self.swift_dir, ring_name='account')
return self.account_ring return self.account_ring
def _listdir(self, path):
try:
return os.listdir(path)
except OSError as e:
self.logger.error(_('ERROR: Failed to get paths to drive '
'partitions: %s') % e)
return []
def get_paths(self): def get_paths(self):
""" """
Get paths to all of the partitions on each drive to be processed. Get paths to all of the partitions on each drive to be processed.
@@ -77,7 +85,7 @@ class ContainerUpdater(Daemon):
:returns: a list of paths :returns: a list of paths
""" """
paths = [] paths = []
for device in os.listdir(self.devices): for device in self._listdir(self.devices):
dev_path = os.path.join(self.devices, device) dev_path = os.path.join(self.devices, device)
if self.mount_check and not ismount(dev_path): if self.mount_check and not ismount(dev_path):
self.logger.warn(_('%s is not mounted'), device) self.logger.warn(_('%s is not mounted'), device)
@@ -85,7 +93,7 @@ class ContainerUpdater(Daemon):
con_path = os.path.join(dev_path, DATADIR) con_path = os.path.join(dev_path, DATADIR)
if not os.path.exists(con_path): if not os.path.exists(con_path):
continue continue
for partition in os.listdir(con_path): for partition in self._listdir(con_path):
paths.append(os.path.join(con_path, partition)) paths.append(os.path.join(con_path, partition))
shuffle(paths) shuffle(paths)
return paths return paths

View File

@@ -14,12 +14,14 @@
# limitations under the License. # limitations under the License.
import cPickle as pickle import cPickle as pickle
import mock
import os import os
import unittest import unittest
from contextlib import closing from contextlib import closing
from gzip import GzipFile from gzip import GzipFile
from shutil import rmtree from shutil import rmtree
from tempfile import mkdtemp from tempfile import mkdtemp
from test.unit import FakeLogger
from eventlet import spawn, Timeout, listen from eventlet import spawn, Timeout, listen
@@ -157,6 +159,44 @@ class TestContainerUpdater(unittest.TestCase):
self.assertEquals(info['reported_object_count'], 1) self.assertEquals(info['reported_object_count'], 1)
self.assertEquals(info['reported_bytes_used'], 3) self.assertEquals(info['reported_bytes_used'], 3)
@mock.patch('os.listdir')
def test_listdir_with_exception(self, mock_listdir):
e = OSError('permission_denied')
mock_listdir.side_effect = e
cu = container_updater.ContainerUpdater({
'devices': self.devices_dir,
'mount_check': 'false',
'swift_dir': self.testdir,
'interval': '1',
'concurrency': '1',
'node_timeout': '15',
'account_suppression_time': 0
})
cu.logger = FakeLogger()
paths = cu.get_paths()
self.assertEqual(paths, [])
log_lines = cu.logger.get_lines_for_level('error')
msg = ('ERROR: Failed to get paths to drive partitions: '
'permission_denied')
self.assertEqual(log_lines[0], msg)
@mock.patch('os.listdir', return_value='bar/')
def test_listdir_without_exception(self, mock_listdir):
cu = container_updater.ContainerUpdater({
'devices': self.devices_dir,
'mount_check': 'false',
'swift_dir': self.testdir,
'interval': '1',
'concurrency': '1',
'node_timeout': '15',
'account_suppression_time': 0
})
cu.logger = FakeLogger()
path = cu._listdir('foo/bar/')
self.assertEqual(path, 'bar/')
log_lines = cu.logger.get_lines_for_level('error')
self.assertEqual(len(log_lines), 0)
def test_unicode(self): def test_unicode(self):
cu = container_updater.ContainerUpdater({ cu = container_updater.ContainerUpdater({
'devices': self.devices_dir, 'devices': self.devices_dir,