Add checksum to object extended attributes
Currently, our integrity checking for objects is pretty weak when it comes to object metadata. If the extended attributes on a .data or .meta file get corrupted in such a way that we can still unpickle it, we don't have anything that detects that. This could be especially bad with encrypted etags; if the encrypted etag (X-Object-Sysmeta-Crypto-Etag or whatever it is) gets some bits flipped, then we'll cheerfully decrypt the cipherjunk into plainjunk, then send it to the client. Net effect is that the client sees a GET response with an ETag that doesn't match the MD5 of the object *and* Swift has no way of detecting and quarantining this object. Note that, with an unencrypted object, if the ETag metadatum gets mangled, then the object will be quarantined by the object server or auditor, whichever notices first. As part of this commit, I also ripped out some mocking of getxattr/setxattr in tests. It appears to be there to allow unit tests to run on systems where /tmp doesn't support xattrs. However, since the mock is keyed off of inode number and inode numbers get re-used, there's lots of leakage between different test runs. On a real FS, unlinking a file and then creating a new one of the same name will also reset the xattrs; this isn't the case with the mock. The mock was pretty old; Ubuntu 12.04 and up all support xattrs in /tmp, and recent Red Hat / CentOS releases do too. The xattr mock was added in 2011; maybe it was to support Ubuntu Lucid Lynx? Bonus: now you can pause a test with the debugger, inspect its files in /tmp, and actually see the xattrs along with the data. Since this patch now uses a real filesystem for testing filesystem operations, tests are skipped if the underlying filesystem does not support setting xattrs (eg tmpfs or more than 4k of xattrs on ext4). References to "/tmp" have been replaced with calls to tempfile.gettempdir(). This will allow setting the TMPDIR envvar in test setup and getting an XFS filesystem instead of ext4 or tmpfs. THIS PATCH SIGNIFICANTLY CHANGES TESTING ENVIRONMENTS With this patch, every test environment will require TMPDIR to be using a filesystem that supports at least 4k of extended attributes. Neither ext4 nor tempfs support this. XFS is recommended. So why all the SkipTests? Why not simply raise an error? We still need the tests to run on the base image for OpenStack's CI system. Since we were previously mocking out xattr, there wasn't a problem, but we also weren't actually testing anything. This patch adds functionality to validate xattr data, so we need to drop the mock. `test.unit.skip_if_no_xattrs()` is also imported into `test.functional` so that functional tests can import it from the functional test namespace. The related OpenStack CI infrastructure changes are made in https://review.openstack.org/#/c/394600/. Co-Authored-By: John Dickinson <me@not.mn> Change-Id: I98a37c0d451f4960b7a12f648e4405c6c6716808
This commit is contained in:
parent
feee399840
commit
728b4ba140
@ -82,6 +82,12 @@ You can run unit tests with ``.unittests``, functional tests with
|
|||||||
``.functests``, and probe tests with ``.probetests``. There is an
|
``.functests``, and probe tests with ``.probetests``. There is an
|
||||||
additional ``.alltests`` script that wraps the other three.
|
additional ``.alltests`` script that wraps the other three.
|
||||||
|
|
||||||
|
To fully run the tests, the target environment must use a filesystem that
|
||||||
|
supports large xattrs. XFS is strongly recommended. For unit tests and in-
|
||||||
|
process functional tests, either mount ``/tmp`` with XFS or provide another
|
||||||
|
XFS filesystem via the ``TMPDIR`` environment variable. Without this setting,
|
||||||
|
tests should still pass, but a very large number will be skipped.
|
||||||
|
|
||||||
Code Organization
|
Code Organization
|
||||||
~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -77,6 +77,9 @@ To execute the tests:
|
|||||||
--recreate`` or remove the ``.tox`` directory to force ``tox`` to recreate the
|
--recreate`` or remove the ``.tox`` directory to force ``tox`` to recreate the
|
||||||
dependency list.
|
dependency list.
|
||||||
|
|
||||||
|
Swift's tests require having an XFS directory available in ``/tmp`` or
|
||||||
|
in the ``TMPDIR`` environment variable.
|
||||||
|
|
||||||
Swift's functional tests may be executed against a :doc:`development_saio` or
|
Swift's functional tests may be executed against a :doc:`development_saio` or
|
||||||
other running Swift cluster using the command::
|
other running Swift cluster using the command::
|
||||||
|
|
||||||
|
@ -201,6 +201,23 @@ On Fedora 19 or later, you need to place these in ``/etc/rc.d/rc.local``.
|
|||||||
|
|
||||||
On OpenSuse you need to place these in ``/etc/init.d/boot.local``.
|
On OpenSuse you need to place these in ``/etc/init.d/boot.local``.
|
||||||
|
|
||||||
|
Creating an XFS tmp dir
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Tests require having an XFS directory available in ``/tmp`` or in the
|
||||||
|
``TMPDIR`` environment variable. To set up ``/tmp`` with an XFS filesystem,
|
||||||
|
do the following::
|
||||||
|
|
||||||
|
cd ~
|
||||||
|
truncate -s 1GB xfs_file # create 1GB fil for XFS in your home directory
|
||||||
|
mkfs.xfs xfs_file
|
||||||
|
sudo mount -o loop,noatime,nodiratime xfs_file /tmp
|
||||||
|
sudo chmod -R 1777 /tmp
|
||||||
|
|
||||||
|
To persist this, edit and add the following to ``/etc/fstab``::
|
||||||
|
|
||||||
|
/home/swift/xfs_file /tmp xfs rw,noatime,nodiratime,attr2,inode64,noquota 0 0
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
Getting the code
|
Getting the code
|
||||||
----------------
|
----------------
|
||||||
|
@ -105,6 +105,10 @@ class DiskFileXattrNotSupported(DiskFileError):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DiskFileBadMetadataChecksum(DiskFileError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class DeviceUnavailable(SwiftException):
|
class DeviceUnavailable(SwiftException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ import time
|
|||||||
import subprocess
|
import subprocess
|
||||||
import re
|
import re
|
||||||
from swift import gettext_ as _
|
from swift import gettext_ as _
|
||||||
|
import tempfile
|
||||||
|
|
||||||
from swift.common.utils import search_tree, remove_file, write_file
|
from swift.common.utils import search_tree, remove_file, write_file
|
||||||
from swift.common.exceptions import InvalidPidFileException
|
from swift.common.exceptions import InvalidPidFileException
|
||||||
@ -82,7 +83,7 @@ def setup_env():
|
|||||||
"Running as non-root?"))
|
"Running as non-root?"))
|
||||||
|
|
||||||
# Set PYTHON_EGG_CACHE if it isn't already set
|
# Set PYTHON_EGG_CACHE if it isn't already set
|
||||||
os.environ.setdefault('PYTHON_EGG_CACHE', '/tmp')
|
os.environ.setdefault('PYTHON_EGG_CACHE', tempfile.gettempdir())
|
||||||
|
|
||||||
|
|
||||||
def command(func):
|
def command(func):
|
||||||
|
@ -70,7 +70,8 @@ from swift.common.splice import splice, tee
|
|||||||
from swift.common.exceptions import DiskFileQuarantined, DiskFileNotExist, \
|
from swift.common.exceptions import DiskFileQuarantined, DiskFileNotExist, \
|
||||||
DiskFileCollision, DiskFileNoSpace, DiskFileDeviceUnavailable, \
|
DiskFileCollision, DiskFileNoSpace, DiskFileDeviceUnavailable, \
|
||||||
DiskFileDeleted, DiskFileError, DiskFileNotOpen, PathNotDir, \
|
DiskFileDeleted, DiskFileError, DiskFileNotOpen, PathNotDir, \
|
||||||
ReplicationLockTimeout, DiskFileExpired, DiskFileXattrNotSupported
|
ReplicationLockTimeout, DiskFileExpired, DiskFileXattrNotSupported, \
|
||||||
|
DiskFileBadMetadataChecksum
|
||||||
from swift.common.swob import multi_range_iterator
|
from swift.common.swob import multi_range_iterator
|
||||||
from swift.common.storage_policy import (
|
from swift.common.storage_policy import (
|
||||||
get_policy_string, split_policy_string, PolicyError, POLICIES,
|
get_policy_string, split_policy_string, PolicyError, POLICIES,
|
||||||
@ -83,6 +84,7 @@ DEFAULT_RECLAIM_AGE = timedelta(weeks=1).total_seconds()
|
|||||||
HASH_FILE = 'hashes.pkl'
|
HASH_FILE = 'hashes.pkl'
|
||||||
HASH_INVALIDATIONS_FILE = 'hashes.invalid'
|
HASH_INVALIDATIONS_FILE = 'hashes.invalid'
|
||||||
METADATA_KEY = 'user.swift.metadata'
|
METADATA_KEY = 'user.swift.metadata'
|
||||||
|
METADATA_CHECKSUM_KEY = 'user.swift.metadata_checksum'
|
||||||
DROP_CACHE_WINDOW = 1024 * 1024
|
DROP_CACHE_WINDOW = 1024 * 1024
|
||||||
# These are system-set metadata keys that cannot be changed with a POST.
|
# These are system-set metadata keys that cannot be changed with a POST.
|
||||||
# They should be lowercase.
|
# They should be lowercase.
|
||||||
@ -145,16 +147,33 @@ def read_metadata(fd):
|
|||||||
(key or '')))
|
(key or '')))
|
||||||
key += 1
|
key += 1
|
||||||
except (IOError, OSError) as e:
|
except (IOError, OSError) as e:
|
||||||
for err in 'ENOTSUP', 'EOPNOTSUPP':
|
if errno.errorcode.get(e.errno) in ('ENOTSUP', 'EOPNOTSUPP'):
|
||||||
if hasattr(errno, err) and e.errno == getattr(errno, err):
|
msg = "Filesystem at %s does not support xattr"
|
||||||
msg = "Filesystem at %s does not support xattr" % \
|
logging.exception(msg, _get_filename(fd))
|
||||||
_get_filename(fd)
|
|
||||||
logging.exception(msg)
|
|
||||||
raise DiskFileXattrNotSupported(e)
|
raise DiskFileXattrNotSupported(e)
|
||||||
if e.errno == errno.ENOENT:
|
if e.errno == errno.ENOENT:
|
||||||
raise DiskFileNotExist()
|
raise DiskFileNotExist()
|
||||||
# TODO: we might want to re-raise errors that don't denote a missing
|
# TODO: we might want to re-raise errors that don't denote a missing
|
||||||
# xattr here. Seems to be ENODATA on linux and ENOATTR on BSD/OSX.
|
# xattr here. Seems to be ENODATA on linux and ENOATTR on BSD/OSX.
|
||||||
|
|
||||||
|
metadata_checksum = None
|
||||||
|
try:
|
||||||
|
metadata_checksum = xattr.getxattr(fd, METADATA_CHECKSUM_KEY)
|
||||||
|
except (IOError, OSError) as e:
|
||||||
|
# All the interesting errors were handled above; the only thing left
|
||||||
|
# here is ENODATA / ENOATTR to indicate that this attribute doesn't
|
||||||
|
# exist. This is fine; it just means that this object predates the
|
||||||
|
# introduction of metadata checksums.
|
||||||
|
pass
|
||||||
|
|
||||||
|
if metadata_checksum:
|
||||||
|
computed_checksum = hashlib.md5(metadata).hexdigest()
|
||||||
|
if metadata_checksum != computed_checksum:
|
||||||
|
raise DiskFileBadMetadataChecksum(
|
||||||
|
"Metadata checksum mismatch for %s: "
|
||||||
|
"stored checksum='%s', computed='%s'" % (
|
||||||
|
fd, metadata_checksum, computed_checksum))
|
||||||
|
|
||||||
# strings are utf-8 encoded when written, but have not always been
|
# strings are utf-8 encoded when written, but have not always been
|
||||||
# (see https://bugs.launchpad.net/swift/+bug/1678018) so encode them again
|
# (see https://bugs.launchpad.net/swift/+bug/1678018) so encode them again
|
||||||
# when read
|
# when read
|
||||||
@ -169,21 +188,23 @@ def write_metadata(fd, metadata, xattr_size=65536):
|
|||||||
:param metadata: metadata to write
|
:param metadata: metadata to write
|
||||||
"""
|
"""
|
||||||
metastr = pickle.dumps(_encode_metadata(metadata), PICKLE_PROTOCOL)
|
metastr = pickle.dumps(_encode_metadata(metadata), PICKLE_PROTOCOL)
|
||||||
|
metastr_md5 = hashlib.md5(metastr).hexdigest()
|
||||||
key = 0
|
key = 0
|
||||||
while metastr:
|
|
||||||
try:
|
try:
|
||||||
|
while metastr:
|
||||||
xattr.setxattr(fd, '%s%s' % (METADATA_KEY, key or ''),
|
xattr.setxattr(fd, '%s%s' % (METADATA_KEY, key or ''),
|
||||||
metastr[:xattr_size])
|
metastr[:xattr_size])
|
||||||
metastr = metastr[xattr_size:]
|
metastr = metastr[xattr_size:]
|
||||||
key += 1
|
key += 1
|
||||||
|
xattr.setxattr(fd, METADATA_CHECKSUM_KEY, metastr_md5)
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
for err in 'ENOTSUP', 'EOPNOTSUPP':
|
# errno module doesn't always have both of these, hence the ugly
|
||||||
if hasattr(errno, err) and e.errno == getattr(errno, err):
|
# check
|
||||||
msg = "Filesystem at %s does not support xattr" % \
|
if errno.errorcode.get(e.errno) in ('ENOTSUP', 'EOPNOTSUPP'):
|
||||||
_get_filename(fd)
|
msg = "Filesystem at %s does not support xattr"
|
||||||
logging.exception(msg)
|
logging.exception(msg, _get_filename(fd))
|
||||||
raise DiskFileXattrNotSupported(e)
|
raise DiskFileXattrNotSupported(e)
|
||||||
if e.errno in (errno.ENOSPC, errno.EDQUOT):
|
elif e.errno in (errno.ENOSPC, errno.EDQUOT):
|
||||||
msg = "No space left on device for %s" % _get_filename(fd)
|
msg = "No space left on device for %s" % _get_filename(fd)
|
||||||
logging.exception(msg)
|
logging.exception(msg)
|
||||||
raise DiskFileNoSpace()
|
raise DiskFileNoSpace()
|
||||||
@ -2389,6 +2410,8 @@ class BaseDiskFile(object):
|
|||||||
return read_metadata(source)
|
return read_metadata(source)
|
||||||
except (DiskFileXattrNotSupported, DiskFileNotExist):
|
except (DiskFileXattrNotSupported, DiskFileNotExist):
|
||||||
raise
|
raise
|
||||||
|
except DiskFileBadMetadataChecksum as err:
|
||||||
|
raise self._quarantine(quarantine_filename, str(err))
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
raise self._quarantine(
|
raise self._quarantine(
|
||||||
quarantine_filename,
|
quarantine_filename,
|
||||||
|
@ -31,7 +31,6 @@ 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 unittest2 import SkipTest
|
|
||||||
|
|
||||||
from six.moves.configparser import ConfigParser, NoSectionError
|
from six.moves.configparser import ConfigParser, NoSectionError
|
||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
@ -44,10 +43,13 @@ from swift.common.utils import set_swift_dir
|
|||||||
from test import get_config, listen_zero
|
from test import get_config, listen_zero
|
||||||
from test.functional.swift_test_client import Account, Connection, Container, \
|
from test.functional.swift_test_client import Account, Connection, Container, \
|
||||||
ResponseError
|
ResponseError
|
||||||
# This has the side effect of mocking out the xattr module so that unit tests
|
|
||||||
# (and in this case, when in-process functional tests are called for) can run
|
|
||||||
# on file systems that don't support extended attributes.
|
|
||||||
from test.unit import debug_logger, FakeMemcache
|
from test.unit import debug_logger, FakeMemcache
|
||||||
|
# importing skip_if_no_xattrs so that functional tests can grab it from the
|
||||||
|
# test.functional namespace. Importing SkipTest so this works under both
|
||||||
|
# nose and testr test runners.
|
||||||
|
from test.unit import skip_if_no_xattrs as real_skip_if_no_xattrs
|
||||||
|
from test.unit import SkipTest
|
||||||
|
|
||||||
from swift.common import constraints, utils, ring, storage_policy
|
from swift.common import constraints, utils, ring, storage_policy
|
||||||
from swift.common.ring import Ring
|
from swift.common.ring import Ring
|
||||||
@ -110,6 +112,7 @@ insecure = False
|
|||||||
in_process = False
|
in_process = False
|
||||||
_testdir = _test_servers = _test_coros = _test_socks = None
|
_testdir = _test_servers = _test_coros = _test_socks = None
|
||||||
policy_specified = None
|
policy_specified = None
|
||||||
|
skip_if_no_xattrs = None
|
||||||
|
|
||||||
|
|
||||||
class FakeMemcacheMiddleware(MemcacheMiddleware):
|
class FakeMemcacheMiddleware(MemcacheMiddleware):
|
||||||
@ -660,6 +663,7 @@ def get_cluster_info():
|
|||||||
def setup_package():
|
def setup_package():
|
||||||
|
|
||||||
global policy_specified
|
global policy_specified
|
||||||
|
global skip_if_no_xattrs
|
||||||
policy_specified = os.environ.get('SWIFT_TEST_POLICY')
|
policy_specified = os.environ.get('SWIFT_TEST_POLICY')
|
||||||
in_process_env = os.environ.get('SWIFT_TEST_IN_PROCESS')
|
in_process_env = os.environ.get('SWIFT_TEST_IN_PROCESS')
|
||||||
if in_process_env is not None:
|
if in_process_env is not None:
|
||||||
@ -698,6 +702,7 @@ def setup_package():
|
|||||||
if in_process:
|
if in_process:
|
||||||
in_mem_obj_env = os.environ.get('SWIFT_TEST_IN_MEMORY_OBJ')
|
in_mem_obj_env = os.environ.get('SWIFT_TEST_IN_MEMORY_OBJ')
|
||||||
in_mem_obj = utils.config_true_value(in_mem_obj_env)
|
in_mem_obj = utils.config_true_value(in_mem_obj_env)
|
||||||
|
skip_if_no_xattrs = real_skip_if_no_xattrs
|
||||||
try:
|
try:
|
||||||
in_process_setup(the_object_server=(
|
in_process_setup(the_object_server=(
|
||||||
mem_object_server if in_mem_obj else object_server))
|
mem_object_server if in_mem_obj else object_server))
|
||||||
@ -705,6 +710,8 @@ def setup_package():
|
|||||||
print(('Exception during in-process setup: %s'
|
print(('Exception during in-process setup: %s'
|
||||||
% str(exc)), file=sys.stderr)
|
% str(exc)), file=sys.stderr)
|
||||||
raise
|
raise
|
||||||
|
else:
|
||||||
|
skip_if_no_xattrs = lambda: None
|
||||||
|
|
||||||
global web_front_end
|
global web_front_end
|
||||||
web_front_end = config.get('web_front_end', 'integral')
|
web_front_end = config.get('web_front_end', 'integral')
|
||||||
|
@ -834,6 +834,9 @@ class TestAccount(unittest2.TestCase):
|
|||||||
if tf.skip:
|
if tf.skip:
|
||||||
raise SkipTest
|
raise SkipTest
|
||||||
|
|
||||||
|
if tf.in_process:
|
||||||
|
tf.skip_if_no_xattrs()
|
||||||
|
|
||||||
def post(url, token, parsed, conn, extra_headers):
|
def post(url, token, parsed, conn, extra_headers):
|
||||||
headers = {'X-Auth-Token': token}
|
headers = {'X-Auth-Token': token}
|
||||||
headers.update(extra_headers)
|
headers.update(extra_headers)
|
||||||
|
@ -438,6 +438,9 @@ class TestContainer(unittest2.TestCase):
|
|||||||
if tf.skip:
|
if tf.skip:
|
||||||
raise SkipTest
|
raise SkipTest
|
||||||
|
|
||||||
|
if tf.in_process:
|
||||||
|
tf.skip_if_no_xattrs()
|
||||||
|
|
||||||
def post(url, token, parsed, conn, extra_headers):
|
def post(url, token, parsed, conn, extra_headers):
|
||||||
headers = {'X-Auth-Token': token}
|
headers = {'X-Auth-Token': token}
|
||||||
headers.update(extra_headers)
|
headers.update(extra_headers)
|
||||||
@ -580,6 +583,9 @@ class TestContainer(unittest2.TestCase):
|
|||||||
def test_cross_account_public_container(self):
|
def test_cross_account_public_container(self):
|
||||||
if tf.skip or tf.skip2:
|
if tf.skip or tf.skip2:
|
||||||
raise SkipTest
|
raise SkipTest
|
||||||
|
|
||||||
|
if tf.in_process:
|
||||||
|
tf.skip_if_no_xattrs()
|
||||||
# Obtain the first account's string
|
# Obtain the first account's string
|
||||||
first_account = ['unknown']
|
first_account = ['unknown']
|
||||||
|
|
||||||
@ -649,6 +655,9 @@ class TestContainer(unittest2.TestCase):
|
|||||||
def test_nonadmin_user(self):
|
def test_nonadmin_user(self):
|
||||||
if tf.skip or tf.skip3:
|
if tf.skip or tf.skip3:
|
||||||
raise SkipTest
|
raise SkipTest
|
||||||
|
|
||||||
|
if tf.in_process:
|
||||||
|
tf.skip_if_no_xattrs()
|
||||||
# Obtain the first account's string
|
# Obtain the first account's string
|
||||||
first_account = ['unknown']
|
first_account = ['unknown']
|
||||||
|
|
||||||
@ -1562,6 +1571,9 @@ class TestContainer(unittest2.TestCase):
|
|||||||
if 'container_quotas' not in cluster_info:
|
if 'container_quotas' not in cluster_info:
|
||||||
raise SkipTest('Container quotas not enabled')
|
raise SkipTest('Container quotas not enabled')
|
||||||
|
|
||||||
|
if tf.in_process:
|
||||||
|
tf.skip_if_no_xattrs()
|
||||||
|
|
||||||
def post(url, token, parsed, conn, name, value):
|
def post(url, token, parsed, conn, name, value):
|
||||||
conn.request('POST', parsed.path + '/' + self.name, '',
|
conn.request('POST', parsed.path + '/' + self.name, '',
|
||||||
{'X-Auth-Token': token, name: value})
|
{'X-Auth-Token': token, name: value})
|
||||||
|
@ -42,6 +42,9 @@ class TestObject(unittest2.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
if tf.skip or tf.skip2:
|
if tf.skip or tf.skip2:
|
||||||
raise SkipTest
|
raise SkipTest
|
||||||
|
|
||||||
|
if tf.in_process:
|
||||||
|
tf.skip_if_no_xattrs()
|
||||||
self.container = uuid4().hex
|
self.container = uuid4().hex
|
||||||
|
|
||||||
self.containers = []
|
self.containers = []
|
||||||
|
@ -379,6 +379,9 @@ class TestObjectVersioning(Base):
|
|||||||
self.assertNotIn('x-object-manifest', resp_headers)
|
self.assertNotIn('x-object-manifest', resp_headers)
|
||||||
|
|
||||||
def _test_versioning_dlo_setup(self):
|
def _test_versioning_dlo_setup(self):
|
||||||
|
if tf.in_process:
|
||||||
|
tf.skip_if_no_xattrs()
|
||||||
|
|
||||||
container = self.env.container
|
container = self.env.container
|
||||||
versions_container = self.env.versions_container
|
versions_container = self.env.versions_container
|
||||||
obj_name = Utils.create_name()
|
obj_name = Utils.create_name()
|
||||||
@ -695,6 +698,8 @@ class TestSloWithVersioning(unittest2.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
if 'slo' not in cluster_info:
|
if 'slo' not in cluster_info:
|
||||||
raise SkipTest("SLO not enabled")
|
raise SkipTest("SLO not enabled")
|
||||||
|
if tf.in_process:
|
||||||
|
tf.skip_if_no_xattrs()
|
||||||
|
|
||||||
self.conn = Connection(tf.config)
|
self.conn = Connection(tf.config)
|
||||||
self.conn.authenticate()
|
self.conn.authenticate()
|
||||||
|
@ -87,16 +87,19 @@ class BaseEnv(object):
|
|||||||
|
|
||||||
|
|
||||||
class Base(unittest2.TestCase):
|
class Base(unittest2.TestCase):
|
||||||
# subclasses may override env class
|
|
||||||
env = BaseEnv
|
env = BaseEnv
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
cls.env.tearDown()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
cls.env.setUp()
|
cls.env.setUp()
|
||||||
|
|
||||||
@classmethod
|
def setUp(self):
|
||||||
def tearDownClass(cls):
|
if tf.in_process:
|
||||||
cls.env.tearDown()
|
tf.skip_if_no_xattrs()
|
||||||
|
|
||||||
def assert_body(self, body):
|
def assert_body(self, body):
|
||||||
response_body = self.env.conn.response.read()
|
response_body = self.env.conn.response.read()
|
||||||
@ -2721,6 +2724,9 @@ class TestServiceToken(unittest2.TestCase):
|
|||||||
if tf.skip_service_tokens:
|
if tf.skip_service_tokens:
|
||||||
raise SkipTest
|
raise SkipTest
|
||||||
|
|
||||||
|
if tf.in_process:
|
||||||
|
tf.skip_if_no_xattrs()
|
||||||
|
|
||||||
self.SET_TO_USERS_TOKEN = 1
|
self.SET_TO_USERS_TOKEN = 1
|
||||||
self.SET_TO_SERVICE_TOKEN = 2
|
self.SET_TO_SERVICE_TOKEN = 2
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ from __future__ import print_function
|
|||||||
import os
|
import os
|
||||||
import copy
|
import copy
|
||||||
import logging
|
import logging
|
||||||
import errno
|
|
||||||
from six.moves import range
|
from six.moves import range
|
||||||
from six import BytesIO
|
from six import BytesIO
|
||||||
import sys
|
import sys
|
||||||
@ -32,11 +31,14 @@ import time
|
|||||||
import eventlet
|
import eventlet
|
||||||
from eventlet import greenpool, debug as eventlet_debug
|
from eventlet import greenpool, debug as eventlet_debug
|
||||||
from eventlet.green import socket
|
from eventlet.green import socket
|
||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp, mkstemp, gettempdir
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
import signal
|
import signal
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
|
import errno
|
||||||
|
import xattr
|
||||||
|
|
||||||
|
|
||||||
from swift.common.utils import Timestamp, NOTICE
|
from swift.common.utils import Timestamp, NOTICE
|
||||||
from test import get_config
|
from test import get_config
|
||||||
@ -57,7 +59,12 @@ import six.moves.cPickle as pickle
|
|||||||
from gzip import GzipFile
|
from gzip import GzipFile
|
||||||
import mock as mocklib
|
import mock as mocklib
|
||||||
import inspect
|
import inspect
|
||||||
from nose import SkipTest
|
import unittest
|
||||||
|
import unittest2
|
||||||
|
|
||||||
|
|
||||||
|
class SkipTest(unittest2.SkipTest, unittest.SkipTest):
|
||||||
|
pass
|
||||||
|
|
||||||
EMPTY_ETAG = md5().hexdigest()
|
EMPTY_ETAG = md5().hexdigest()
|
||||||
|
|
||||||
@ -402,36 +409,6 @@ def tmpfile(content):
|
|||||||
finally:
|
finally:
|
||||||
os.unlink(file_name)
|
os.unlink(file_name)
|
||||||
|
|
||||||
xattr_data = {}
|
|
||||||
|
|
||||||
|
|
||||||
def _get_inode(fd):
|
|
||||||
if not isinstance(fd, int):
|
|
||||||
try:
|
|
||||||
fd = fd.fileno()
|
|
||||||
except AttributeError:
|
|
||||||
return os.stat(fd).st_ino
|
|
||||||
return os.fstat(fd).st_ino
|
|
||||||
|
|
||||||
|
|
||||||
def _setxattr(fd, k, v):
|
|
||||||
inode = _get_inode(fd)
|
|
||||||
data = xattr_data.get(inode, {})
|
|
||||||
data[k] = v
|
|
||||||
xattr_data[inode] = data
|
|
||||||
|
|
||||||
|
|
||||||
def _getxattr(fd, k):
|
|
||||||
inode = _get_inode(fd)
|
|
||||||
data = xattr_data.get(inode, {}).get(k)
|
|
||||||
if not data:
|
|
||||||
raise IOError(errno.ENODATA, "Fake IOError")
|
|
||||||
return data
|
|
||||||
|
|
||||||
import xattr
|
|
||||||
xattr.setxattr = _setxattr
|
|
||||||
xattr.getxattr = _getxattr
|
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def temptree(files, contents=''):
|
def temptree(files, contents=''):
|
||||||
@ -1289,3 +1266,51 @@ def fake_ec_node_response(node_frags, policy):
|
|||||||
return StubResponse(200, body, headers)
|
return StubResponse(200, body, headers)
|
||||||
|
|
||||||
return get_response
|
return get_response
|
||||||
|
|
||||||
|
|
||||||
|
supports_xattr_cached_val = None
|
||||||
|
|
||||||
|
|
||||||
|
def xattr_supported_check():
|
||||||
|
"""
|
||||||
|
This check simply sets more than 4k of metadata on a tempfile and
|
||||||
|
returns True if it worked and False if not.
|
||||||
|
|
||||||
|
We want to use *more* than 4k of metadata in this check because
|
||||||
|
some filesystems (eg ext4) only allow one blocksize worth of
|
||||||
|
metadata. The XFS filesystem doesn't have this limit, and so this
|
||||||
|
check returns True when TMPDIR is XFS. This check will return
|
||||||
|
False under ext4 (which supports xattrs <= 4k) and tmpfs (which
|
||||||
|
doesn't support xattrs at all).
|
||||||
|
|
||||||
|
"""
|
||||||
|
global supports_xattr_cached_val
|
||||||
|
|
||||||
|
if supports_xattr_cached_val is not None:
|
||||||
|
return supports_xattr_cached_val
|
||||||
|
|
||||||
|
# assume the worst -- xattrs aren't supported
|
||||||
|
supports_xattr_cached_val = False
|
||||||
|
|
||||||
|
big_val = 'x' * (4096 + 1) # more than 4k of metadata
|
||||||
|
try:
|
||||||
|
fd, tmppath = mkstemp()
|
||||||
|
xattr.setxattr(fd, 'user.swift.testing_key', big_val)
|
||||||
|
except IOError as e:
|
||||||
|
if errno.errorcode.get(e.errno) in ('ENOSPC', 'ENOTSUP', 'EOPNOTSUPP'):
|
||||||
|
# filesystem does not support xattr of this size
|
||||||
|
return False
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
supports_xattr_cached_val = True
|
||||||
|
return True
|
||||||
|
finally:
|
||||||
|
# clean up the tmpfile
|
||||||
|
os.close(fd)
|
||||||
|
os.unlink(tmppath)
|
||||||
|
|
||||||
|
|
||||||
|
def skip_if_no_xattrs():
|
||||||
|
if not xattr_supported_check():
|
||||||
|
raise SkipTest('Large xattrs not supported in `%s`. Skipping test' %
|
||||||
|
gettempdir())
|
||||||
|
@ -20,7 +20,7 @@ from shutil import rmtree
|
|||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
|
|
||||||
from six.moves import cStringIO as StringIO
|
from six.moves import cStringIO as StringIO
|
||||||
from test.unit import patch_policies, write_fake_ring
|
from test.unit import patch_policies, write_fake_ring, skip_if_no_xattrs
|
||||||
|
|
||||||
from swift.common import ring, utils
|
from swift.common import ring, utils
|
||||||
from swift.common.swob import Request
|
from swift.common.swob import Request
|
||||||
@ -40,6 +40,7 @@ from swift.obj.diskfile import write_metadata
|
|||||||
StoragePolicy(3, 'three', False)])
|
StoragePolicy(3, 'three', False)])
|
||||||
class TestCliInfoBase(unittest.TestCase):
|
class TestCliInfoBase(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.orig_hp = utils.HASH_PATH_PREFIX, utils.HASH_PATH_SUFFIX
|
self.orig_hp = utils.HASH_PATH_PREFIX, utils.HASH_PATH_SUFFIX
|
||||||
utils.HASH_PATH_PREFIX = 'info'
|
utils.HASH_PATH_PREFIX = 'info'
|
||||||
utils.HASH_PATH_SUFFIX = 'info'
|
utils.HASH_PATH_SUFFIX = 'info'
|
||||||
|
@ -26,11 +26,12 @@ from swift.common.storage_policy import (
|
|||||||
|
|
||||||
from swift.obj.diskfile import write_metadata
|
from swift.obj.diskfile import write_metadata
|
||||||
|
|
||||||
from test.unit import FakeLogger
|
from test.unit import FakeLogger, skip_if_no_xattrs
|
||||||
|
|
||||||
|
|
||||||
class TestRelinker(unittest.TestCase):
|
class TestRelinker(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.logger = FakeLogger()
|
self.logger = FakeLogger()
|
||||||
self.testdir = tempfile.mkdtemp()
|
self.testdir = tempfile.mkdtemp()
|
||||||
self.devices = os.path.join(self.testdir, 'node')
|
self.devices = os.path.join(self.testdir, 'node')
|
||||||
|
@ -1425,7 +1425,7 @@ class TestCommands(unittest.TestCase, RunSwiftRingBuilderMixin):
|
|||||||
self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
|
self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
|
||||||
|
|
||||||
def test_validate_non_existent_file(self):
|
def test_validate_non_existent_file(self):
|
||||||
rand_file = '%s/%s' % ('/tmp', str(uuid.uuid4()))
|
rand_file = '%s/%s' % (tempfile.gettempdir(), str(uuid.uuid4()))
|
||||||
argv = ["", rand_file, "validate"]
|
argv = ["", rand_file, "validate"]
|
||||||
self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
|
self.assertSystemExit(EXIT_ERROR, ringbuilder.main, argv)
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ from swift.common.ring import Ring
|
|||||||
from swift.common.swob import Request
|
from swift.common.swob import Request
|
||||||
from swift.obj import diskfile
|
from swift.obj import diskfile
|
||||||
|
|
||||||
from test.unit import FakeLogger
|
from test.unit import FakeLogger, skip_if_no_xattrs
|
||||||
from test.unit.common.middleware.crypto.crypto_helpers import (
|
from test.unit.common.middleware.crypto.crypto_helpers import (
|
||||||
md5hex, encrypt, TEST_KEYMASTER_CONF)
|
md5hex, encrypt, TEST_KEYMASTER_CONF)
|
||||||
from test.unit.helpers import setup_servers, teardown_servers
|
from test.unit.helpers import setup_servers, teardown_servers
|
||||||
@ -54,6 +54,7 @@ class TestCryptoPipelineChanges(unittest.TestCase):
|
|||||||
cls._test_context = None
|
cls._test_context = None
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.plaintext = 'unencrypted body content'
|
self.plaintext = 'unencrypted body content'
|
||||||
self.plaintext_etag = md5hex(self.plaintext)
|
self.plaintext_etag = md5hex(self.plaintext)
|
||||||
self._setup_crypto_app()
|
self._setup_crypto_app()
|
||||||
|
@ -268,7 +268,8 @@ class TestReconSuccess(TestCase):
|
|||||||
return app
|
return app
|
||||||
|
|
||||||
def _create_ring(self, ringpath, replica_map, devs, part_shift):
|
def _create_ring(self, ringpath, replica_map, devs, part_shift):
|
||||||
ring.RingData(replica_map, devs, part_shift).save(ringpath)
|
ring.RingData(replica_map, devs, part_shift).save(ringpath,
|
||||||
|
mtime=None)
|
||||||
|
|
||||||
def _create_rings(self):
|
def _create_rings(self):
|
||||||
# make the rings unique so they have different md5 sums
|
# make the rings unique so they have different md5 sums
|
||||||
|
@ -20,6 +20,7 @@ import unittest
|
|||||||
import os
|
import os
|
||||||
import mock
|
import mock
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
from tempfile import gettempdir
|
||||||
|
|
||||||
from swift.common.linkat import linkat
|
from swift.common.linkat import linkat
|
||||||
from swift.common.utils import O_TMPFILE
|
from swift.common.utils import O_TMPFILE
|
||||||
@ -42,7 +43,7 @@ class TestLinkat(unittest.TestCase):
|
|||||||
with open('/dev/null', 'r') as fd:
|
with open('/dev/null', 'r') as fd:
|
||||||
self.assertRaises(IOError, linkat,
|
self.assertRaises(IOError, linkat,
|
||||||
linkat.AT_FDCWD, "/proc/self/fd/%s" % (fd),
|
linkat.AT_FDCWD, "/proc/self/fd/%s" % (fd),
|
||||||
linkat.AT_FDCWD, "/tmp/testlinkat",
|
linkat.AT_FDCWD, "%s/testlinkat" % gettempdir(),
|
||||||
linkat.AT_SYMLINK_FOLLOW)
|
linkat.AT_SYMLINK_FOLLOW)
|
||||||
self.assertEqual(ctypes.get_errno(), 0)
|
self.assertEqual(ctypes.get_errno(), 0)
|
||||||
|
|
||||||
@ -83,8 +84,8 @@ class TestLinkat(unittest.TestCase):
|
|||||||
path = None
|
path = None
|
||||||
ret = -1
|
ret = -1
|
||||||
try:
|
try:
|
||||||
fd = os.open('/tmp', O_TMPFILE | os.O_WRONLY)
|
fd = os.open(gettempdir(), O_TMPFILE | os.O_WRONLY)
|
||||||
path = os.path.join('/tmp', uuid4().hex)
|
path = os.path.join(gettempdir(), uuid4().hex)
|
||||||
ret = linkat(linkat.AT_FDCWD, "/proc/self/fd/%d" % (fd),
|
ret = linkat(linkat.AT_FDCWD, "/proc/self/fd/%d" % (fd),
|
||||||
linkat.AT_FDCWD, path, linkat.AT_SYMLINK_FOLLOW)
|
linkat.AT_FDCWD, path, linkat.AT_SYMLINK_FOLLOW)
|
||||||
self.assertEqual(ret, 0)
|
self.assertEqual(ret, 0)
|
||||||
|
@ -24,6 +24,7 @@ import signal
|
|||||||
import errno
|
import errno
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from time import sleep, time
|
from time import sleep, time
|
||||||
|
import tempfile
|
||||||
|
|
||||||
from six.moves import reload_module
|
from six.moves import reload_module
|
||||||
|
|
||||||
@ -115,7 +116,8 @@ class TestManagerModule(unittest.TestCase):
|
|||||||
]
|
]
|
||||||
self.assertEqual(manager.resource.called_with_args, expected)
|
self.assertEqual(manager.resource.called_with_args, expected)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
manager.os.environ['PYTHON_EGG_CACHE'].startswith('/tmp'))
|
manager.os.environ['PYTHON_EGG_CACHE'].startswith(
|
||||||
|
tempfile.gettempdir()))
|
||||||
|
|
||||||
# test error condition
|
# test error condition
|
||||||
manager.resource = MockResource(error=ValueError())
|
manager.resource = MockResource(error=ValueError())
|
||||||
@ -123,7 +125,8 @@ class TestManagerModule(unittest.TestCase):
|
|||||||
manager.setup_env()
|
manager.setup_env()
|
||||||
self.assertEqual(manager.resource.called_with_args, [])
|
self.assertEqual(manager.resource.called_with_args, [])
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
manager.os.environ['PYTHON_EGG_CACHE'].startswith('/tmp'))
|
manager.os.environ['PYTHON_EGG_CACHE'].startswith(
|
||||||
|
tempfile.gettempdir()))
|
||||||
|
|
||||||
manager.resource = MockResource(error=OSError())
|
manager.resource = MockResource(error=OSError())
|
||||||
manager.os.environ = {}
|
manager.os.environ = {}
|
||||||
|
@ -2018,7 +2018,7 @@ foo = bar
|
|||||||
[section2]
|
[section2]
|
||||||
log_name = yarr'''
|
log_name = yarr'''
|
||||||
# setup a real file
|
# setup a real file
|
||||||
fd, temppath = tempfile.mkstemp(dir='/tmp')
|
fd, temppath = tempfile.mkstemp()
|
||||||
with os.fdopen(fd, 'wb') as f:
|
with os.fdopen(fd, 'wb') as f:
|
||||||
f.write(conf)
|
f.write(conf)
|
||||||
make_filename = lambda: temppath
|
make_filename = lambda: temppath
|
||||||
@ -2067,7 +2067,7 @@ foo = bar
|
|||||||
[section2]
|
[section2]
|
||||||
log_name = %(yarr)s'''
|
log_name = %(yarr)s'''
|
||||||
# setup a real file
|
# setup a real file
|
||||||
fd, temppath = tempfile.mkstemp(dir='/tmp')
|
fd, temppath = tempfile.mkstemp()
|
||||||
with os.fdopen(fd, 'wb') as f:
|
with os.fdopen(fd, 'wb') as f:
|
||||||
f.write(conf)
|
f.write(conf)
|
||||||
make_filename = lambda: temppath
|
make_filename = lambda: temppath
|
||||||
@ -3275,7 +3275,7 @@ cluster_dfw1 = http://dfw1.host/v1/
|
|||||||
tmpdir = mkdtemp()
|
tmpdir = mkdtemp()
|
||||||
try:
|
try:
|
||||||
link = os.path.join(tmpdir, "tmp")
|
link = os.path.join(tmpdir, "tmp")
|
||||||
os.symlink("/tmp", link)
|
os.symlink(tempfile.gettempdir(), link)
|
||||||
self.assertFalse(utils.ismount(link))
|
self.assertFalse(utils.ismount(link))
|
||||||
finally:
|
finally:
|
||||||
shutil.rmtree(tmpdir)
|
shutil.rmtree(tmpdir)
|
||||||
@ -3580,7 +3580,7 @@ cluster_dfw1 = http://dfw1.host/v1/
|
|||||||
tempdir = None
|
tempdir = None
|
||||||
fd = None
|
fd = None
|
||||||
try:
|
try:
|
||||||
tempdir = mkdtemp(dir='/tmp')
|
tempdir = mkdtemp()
|
||||||
fd, temppath = tempfile.mkstemp(dir=tempdir)
|
fd, temppath = tempfile.mkstemp(dir=tempdir)
|
||||||
|
|
||||||
_mock_fsync = mock.Mock()
|
_mock_fsync = mock.Mock()
|
||||||
@ -3618,7 +3618,7 @@ cluster_dfw1 = http://dfw1.host/v1/
|
|||||||
def test_renamer_with_fsync_dir(self):
|
def test_renamer_with_fsync_dir(self):
|
||||||
tempdir = None
|
tempdir = None
|
||||||
try:
|
try:
|
||||||
tempdir = mkdtemp(dir='/tmp')
|
tempdir = mkdtemp()
|
||||||
# Simulate part of object path already existing
|
# Simulate part of object path already existing
|
||||||
part_dir = os.path.join(tempdir, 'objects/1234/')
|
part_dir = os.path.join(tempdir, 'objects/1234/')
|
||||||
os.makedirs(part_dir)
|
os.makedirs(part_dir)
|
||||||
@ -3665,7 +3665,7 @@ cluster_dfw1 = http://dfw1.host/v1/
|
|||||||
tempdir = None
|
tempdir = None
|
||||||
fd = None
|
fd = None
|
||||||
try:
|
try:
|
||||||
tempdir = mkdtemp(dir='/tmp')
|
tempdir = mkdtemp()
|
||||||
os.makedirs(os.path.join(tempdir, 'a/b'))
|
os.makedirs(os.path.join(tempdir, 'a/b'))
|
||||||
# 4 new dirs created
|
# 4 new dirs created
|
||||||
dirpath = os.path.join(tempdir, 'a/b/1/2/3/4')
|
dirpath = os.path.join(tempdir, 'a/b/1/2/3/4')
|
||||||
@ -3788,7 +3788,7 @@ cluster_dfw1 = http://dfw1.host/v1/
|
|||||||
|
|
||||||
@requires_o_tmpfile_support
|
@requires_o_tmpfile_support
|
||||||
def test_link_fd_to_path_linkat_success(self):
|
def test_link_fd_to_path_linkat_success(self):
|
||||||
tempdir = mkdtemp(dir='/tmp')
|
tempdir = mkdtemp()
|
||||||
fd = os.open(tempdir, utils.O_TMPFILE | os.O_WRONLY)
|
fd = os.open(tempdir, utils.O_TMPFILE | os.O_WRONLY)
|
||||||
data = "I'm whatever Gotham needs me to be"
|
data = "I'm whatever Gotham needs me to be"
|
||||||
_m_fsync_dir = mock.Mock()
|
_m_fsync_dir = mock.Mock()
|
||||||
@ -3808,7 +3808,7 @@ cluster_dfw1 = http://dfw1.host/v1/
|
|||||||
|
|
||||||
@requires_o_tmpfile_support
|
@requires_o_tmpfile_support
|
||||||
def test_link_fd_to_path_target_exists(self):
|
def test_link_fd_to_path_target_exists(self):
|
||||||
tempdir = mkdtemp(dir='/tmp')
|
tempdir = mkdtemp()
|
||||||
# Create and write to a file
|
# Create and write to a file
|
||||||
fd, path = tempfile.mkstemp(dir=tempdir)
|
fd, path = tempfile.mkstemp(dir=tempdir)
|
||||||
os.write(fd, "hello world")
|
os.write(fd, "hello world")
|
||||||
@ -3843,7 +3843,7 @@ cluster_dfw1 = http://dfw1.host/v1/
|
|||||||
|
|
||||||
@requires_o_tmpfile_support
|
@requires_o_tmpfile_support
|
||||||
def test_linkat_race_dir_not_exists(self):
|
def test_linkat_race_dir_not_exists(self):
|
||||||
tempdir = mkdtemp(dir='/tmp')
|
tempdir = mkdtemp()
|
||||||
target_dir = os.path.join(tempdir, uuid4().hex)
|
target_dir = os.path.join(tempdir, uuid4().hex)
|
||||||
target_path = os.path.join(target_dir, uuid4().hex)
|
target_path = os.path.join(target_dir, uuid4().hex)
|
||||||
os.mkdir(target_dir)
|
os.mkdir(target_dir)
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from test import unit
|
|
||||||
import unittest
|
import unittest
|
||||||
import mock
|
import mock
|
||||||
import os
|
import os
|
||||||
@ -26,7 +25,7 @@ from tempfile import mkdtemp
|
|||||||
import textwrap
|
import textwrap
|
||||||
from os.path import dirname, basename
|
from os.path import dirname, basename
|
||||||
from test.unit import (debug_logger, patch_policies, make_timestamp_iter,
|
from test.unit import (debug_logger, patch_policies, make_timestamp_iter,
|
||||||
DEFAULT_TEST_EC_TYPE)
|
DEFAULT_TEST_EC_TYPE, skip_if_no_xattrs)
|
||||||
from swift.obj import auditor, replicator
|
from swift.obj import auditor, replicator
|
||||||
from swift.obj.diskfile import (
|
from swift.obj.diskfile import (
|
||||||
DiskFile, write_metadata, invalidate_hash, get_data_dir,
|
DiskFile, write_metadata, invalidate_hash, get_data_dir,
|
||||||
@ -63,6 +62,7 @@ def works_only_once(callable_thing, exception):
|
|||||||
class TestAuditor(unittest.TestCase):
|
class TestAuditor(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.testdir = os.path.join(mkdtemp(), 'tmp_test_object_auditor')
|
self.testdir = os.path.join(mkdtemp(), 'tmp_test_object_auditor')
|
||||||
self.devices = os.path.join(self.testdir, 'node')
|
self.devices = os.path.join(self.testdir, 'node')
|
||||||
self.rcache = os.path.join(self.testdir, 'object.recon')
|
self.rcache = os.path.join(self.testdir, 'object.recon')
|
||||||
@ -118,7 +118,6 @@ class TestAuditor(unittest.TestCase):
|
|||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
rmtree(os.path.dirname(self.testdir), ignore_errors=1)
|
rmtree(os.path.dirname(self.testdir), ignore_errors=1)
|
||||||
unit.xattr_data = {}
|
|
||||||
|
|
||||||
def test_worker_conf_parms(self):
|
def test_worker_conf_parms(self):
|
||||||
def check_common_defaults():
|
def check_common_defaults():
|
||||||
|
@ -44,7 +44,8 @@ from swift.obj.diskfile import MD5_OF_EMPTY_STRING, update_auditor_status
|
|||||||
from test.unit import (mock as unit_mock, temptree, mock_check_drive,
|
from test.unit import (mock as unit_mock, temptree, mock_check_drive,
|
||||||
patch_policies, debug_logger, EMPTY_ETAG,
|
patch_policies, debug_logger, EMPTY_ETAG,
|
||||||
make_timestamp_iter, DEFAULT_TEST_EC_TYPE,
|
make_timestamp_iter, DEFAULT_TEST_EC_TYPE,
|
||||||
requires_o_tmpfile_support, encode_frag_archive_bodies)
|
requires_o_tmpfile_support, encode_frag_archive_bodies,
|
||||||
|
skip_if_no_xattrs)
|
||||||
from nose import SkipTest
|
from nose import SkipTest
|
||||||
from swift.obj import diskfile
|
from swift.obj import diskfile
|
||||||
from swift.common import utils
|
from swift.common import utils
|
||||||
@ -61,6 +62,7 @@ from swift.common.storage_policy import (
|
|||||||
BaseStoragePolicy, REPL_POLICY, EC_POLICY)
|
BaseStoragePolicy, REPL_POLICY, EC_POLICY)
|
||||||
from test.unit.obj.common import write_diskfile
|
from test.unit.obj.common import write_diskfile
|
||||||
|
|
||||||
|
|
||||||
test_policies = [
|
test_policies = [
|
||||||
StoragePolicy(0, name='zero', is_default=True),
|
StoragePolicy(0, name='zero', is_default=True),
|
||||||
ECStoragePolicy(1, name='one', is_default=False,
|
ECStoragePolicy(1, name='one', is_default=False,
|
||||||
@ -145,6 +147,7 @@ def _make_metafilename(meta_timestamp, ctype_timestamp=None):
|
|||||||
class TestDiskFileModuleMethods(unittest.TestCase):
|
class TestDiskFileModuleMethods(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
utils.HASH_PATH_SUFFIX = 'endcap'
|
utils.HASH_PATH_SUFFIX = 'endcap'
|
||||||
utils.HASH_PATH_PREFIX = ''
|
utils.HASH_PATH_PREFIX = ''
|
||||||
# Setup a test ring per policy (stolen from common/test_ring.py)
|
# Setup a test ring per policy (stolen from common/test_ring.py)
|
||||||
@ -682,6 +685,7 @@ class BaseDiskFileTestMixin(object):
|
|||||||
mgr_cls = None
|
mgr_cls = None
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.tmpdir = mkdtemp()
|
self.tmpdir = mkdtemp()
|
||||||
self.testdir = os.path.join(
|
self.testdir = os.path.join(
|
||||||
self.tmpdir, 'tmp_test_obj_server_DiskFile')
|
self.tmpdir, 'tmp_test_obj_server_DiskFile')
|
||||||
@ -3526,6 +3530,13 @@ class DiskFileMixin(BaseDiskFileTestMixin):
|
|||||||
wrong_byte = 'X' if meta_xattr[0] != 'X' else 'Y'
|
wrong_byte = 'X' if meta_xattr[0] != 'X' else 'Y'
|
||||||
xattr.setxattr(data_files[0], "user.swift.metadata",
|
xattr.setxattr(data_files[0], "user.swift.metadata",
|
||||||
wrong_byte + meta_xattr[1:])
|
wrong_byte + meta_xattr[1:])
|
||||||
|
elif invalid_type == 'Subtly-Corrupt-Xattrs':
|
||||||
|
# We have to go below read_metadata/write_metadata to get proper
|
||||||
|
# corruption.
|
||||||
|
meta_xattr = xattr.getxattr(data_files[0], "user.swift.metadata")
|
||||||
|
wrong_checksum = md5(meta_xattr + "some extra stuff").hexdigest()
|
||||||
|
xattr.setxattr(data_files[0], "user.swift.metadata_checksum",
|
||||||
|
wrong_checksum)
|
||||||
elif invalid_type == 'Truncated-Xattrs':
|
elif invalid_type == 'Truncated-Xattrs':
|
||||||
meta_xattr = xattr.getxattr(data_files[0], "user.swift.metadata")
|
meta_xattr = xattr.getxattr(data_files[0], "user.swift.metadata")
|
||||||
xattr.setxattr(data_files[0], "user.swift.metadata",
|
xattr.setxattr(data_files[0], "user.swift.metadata",
|
||||||
@ -3684,6 +3695,11 @@ class DiskFileMixin(BaseDiskFileTestMixin):
|
|||||||
def test_quarantine_corrupt_xattrs(self):
|
def test_quarantine_corrupt_xattrs(self):
|
||||||
self.run_quarantine_invalids('Corrupt-Xattrs')
|
self.run_quarantine_invalids('Corrupt-Xattrs')
|
||||||
|
|
||||||
|
def test_quarantine_subtly_corrupt_xattrs(self):
|
||||||
|
# xattrs that unpickle without error, but whose checksum does not
|
||||||
|
# match
|
||||||
|
self.run_quarantine_invalids('Subtly-Corrupt-Xattrs')
|
||||||
|
|
||||||
def test_quarantine_truncated_xattrs(self):
|
def test_quarantine_truncated_xattrs(self):
|
||||||
self.run_quarantine_invalids('Truncated-Xattrs')
|
self.run_quarantine_invalids('Truncated-Xattrs')
|
||||||
|
|
||||||
@ -3746,18 +3762,7 @@ class DiskFileMixin(BaseDiskFileTestMixin):
|
|||||||
invalid_type='Bad-Content-Length')
|
invalid_type='Bad-Content-Length')
|
||||||
|
|
||||||
def test_quarantine_fstat_oserror(self):
|
def test_quarantine_fstat_oserror(self):
|
||||||
invocations = [0]
|
with mock.patch('os.fstat', side_effect=OSError()):
|
||||||
orig_os_fstat = os.fstat
|
|
||||||
|
|
||||||
def bad_fstat(fd):
|
|
||||||
invocations[0] += 1
|
|
||||||
if invocations[0] == 4:
|
|
||||||
# FIXME - yes, this an icky way to get code coverage ... worth
|
|
||||||
# it?
|
|
||||||
raise OSError()
|
|
||||||
return orig_os_fstat(fd)
|
|
||||||
|
|
||||||
with mock.patch('os.fstat', bad_fstat):
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
DiskFileQuarantined,
|
DiskFileQuarantined,
|
||||||
self._get_open_disk_file)
|
self._get_open_disk_file)
|
||||||
@ -5957,6 +5962,7 @@ class TestSuffixHashes(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.testdir = tempfile.mkdtemp()
|
self.testdir = tempfile.mkdtemp()
|
||||||
self.logger = debug_logger('suffix-hash-test')
|
self.logger = debug_logger('suffix-hash-test')
|
||||||
self.devices = os.path.join(self.testdir, 'node')
|
self.devices = os.path.join(self.testdir, 'node')
|
||||||
|
@ -45,7 +45,7 @@ from swift.obj.reconstructor import REVERT
|
|||||||
from test.unit import (patch_policies, debug_logger, mocked_http_conn,
|
from test.unit import (patch_policies, debug_logger, mocked_http_conn,
|
||||||
FabricatedRing, make_timestamp_iter,
|
FabricatedRing, make_timestamp_iter,
|
||||||
DEFAULT_TEST_EC_TYPE, encode_frag_archive_bodies,
|
DEFAULT_TEST_EC_TYPE, encode_frag_archive_bodies,
|
||||||
quiet_eventlet_exceptions)
|
quiet_eventlet_exceptions, skip_if_no_xattrs)
|
||||||
from test.unit.obj.common import write_diskfile
|
from test.unit.obj.common import write_diskfile
|
||||||
|
|
||||||
|
|
||||||
@ -149,6 +149,7 @@ class TestGlobalSetupObjectReconstructor(unittest.TestCase):
|
|||||||
legacy_durable = False
|
legacy_durable = False
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.testdir = tempfile.mkdtemp()
|
self.testdir = tempfile.mkdtemp()
|
||||||
_create_test_rings(self.testdir)
|
_create_test_rings(self.testdir)
|
||||||
POLICIES[0].object_ring = ring.Ring(self.testdir, ring_name='object')
|
POLICIES[0].object_ring = ring.Ring(self.testdir, ring_name='object')
|
||||||
@ -2387,6 +2388,7 @@ class TestWorkerReconstructor(unittest.TestCase):
|
|||||||
@patch_policies(with_ec_default=True)
|
@patch_policies(with_ec_default=True)
|
||||||
class BaseTestObjectReconstructor(unittest.TestCase):
|
class BaseTestObjectReconstructor(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.policy = POLICIES.default
|
self.policy = POLICIES.default
|
||||||
self.policy.object_ring._rtime = time.time() + 3600
|
self.policy.object_ring._rtime = time.time() + 3600
|
||||||
self.testdir = tempfile.mkdtemp()
|
self.testdir = tempfile.mkdtemp()
|
||||||
|
@ -30,7 +30,8 @@ from eventlet.green import subprocess
|
|||||||
from eventlet import Timeout
|
from eventlet import Timeout
|
||||||
|
|
||||||
from test.unit import (debug_logger, patch_policies, make_timestamp_iter,
|
from test.unit import (debug_logger, patch_policies, make_timestamp_iter,
|
||||||
mocked_http_conn, FakeLogger, mock_check_drive)
|
mocked_http_conn, FakeLogger, mock_check_drive,
|
||||||
|
skip_if_no_xattrs)
|
||||||
from swift.common import utils
|
from swift.common import utils
|
||||||
from swift.common.utils import (hash_path, mkdirs, normalize_timestamp,
|
from swift.common.utils import (hash_path, mkdirs, normalize_timestamp,
|
||||||
storage_directory)
|
storage_directory)
|
||||||
@ -179,6 +180,7 @@ def _create_test_rings(path, devs=None, next_part_power=None):
|
|||||||
class TestObjectReplicator(unittest.TestCase):
|
class TestObjectReplicator(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
utils.HASH_PATH_SUFFIX = 'endcap'
|
utils.HASH_PATH_SUFFIX = 'endcap'
|
||||||
utils.HASH_PATH_PREFIX = ''
|
utils.HASH_PATH_PREFIX = ''
|
||||||
# recon cache path
|
# recon cache path
|
||||||
|
@ -45,9 +45,9 @@ from swift import __version__ as swift_version
|
|||||||
from swift.common.http import is_success
|
from swift.common.http import is_success
|
||||||
from test import listen_zero
|
from test import listen_zero
|
||||||
from test.unit import FakeLogger, debug_logger, mocked_http_conn, \
|
from test.unit import FakeLogger, debug_logger, mocked_http_conn, \
|
||||||
make_timestamp_iter, DEFAULT_TEST_EC_TYPE, mock_check_drive
|
make_timestamp_iter, DEFAULT_TEST_EC_TYPE, skip_if_no_xattrs, \
|
||||||
from test.unit import connect_tcp, readuntil2crlfs, patch_policies, \
|
connect_tcp, readuntil2crlfs, patch_policies, encode_frag_archive_bodies, \
|
||||||
encode_frag_archive_bodies
|
mock_check_drive
|
||||||
from swift.obj import server as object_server
|
from swift.obj import server as object_server
|
||||||
from swift.obj import updater
|
from swift.obj import updater
|
||||||
from swift.obj import diskfile
|
from swift.obj import diskfile
|
||||||
@ -140,6 +140,7 @@ class TestObjectController(unittest.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Set up for testing swift.object.server.ObjectController"""
|
"""Set up for testing swift.object.server.ObjectController"""
|
||||||
|
skip_if_no_xattrs()
|
||||||
utils.HASH_PATH_SUFFIX = 'endcap'
|
utils.HASH_PATH_SUFFIX = 'endcap'
|
||||||
utils.HASH_PATH_PREFIX = 'startcap'
|
utils.HASH_PATH_PREFIX = 'startcap'
|
||||||
self.tmpdir = mkdtemp()
|
self.tmpdir = mkdtemp()
|
||||||
@ -6942,6 +6943,7 @@ class TestObjectController(unittest.TestCase):
|
|||||||
class TestObjectServer(unittest.TestCase):
|
class TestObjectServer(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
# dirs
|
# dirs
|
||||||
self.tmpdir = mkdtemp()
|
self.tmpdir = mkdtemp()
|
||||||
self.tempdir = os.path.join(self.tmpdir, 'tmp_test_obj_server')
|
self.tempdir = os.path.join(self.tmpdir, 'tmp_test_obj_server')
|
||||||
@ -7632,6 +7634,7 @@ class TestZeroCopy(unittest.TestCase):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
if not self._system_can_zero_copy():
|
if not self._system_can_zero_copy():
|
||||||
raise SkipTest("zero-copy support is missing")
|
raise SkipTest("zero-copy support is missing")
|
||||||
|
|
||||||
|
@ -34,8 +34,9 @@ from swift.obj.reconstructor import RebuildingECDiskFileStream, \
|
|||||||
from swift.obj.replicator import ObjectReplicator
|
from swift.obj.replicator import ObjectReplicator
|
||||||
|
|
||||||
from test import listen_zero
|
from test import listen_zero
|
||||||
from test.unit import patch_policies, debug_logger, encode_frag_archive_bodies
|
|
||||||
from test.unit.obj.common import BaseTest
|
from test.unit.obj.common import BaseTest
|
||||||
|
from test.unit import patch_policies, debug_logger, \
|
||||||
|
encode_frag_archive_bodies, skip_if_no_xattrs
|
||||||
|
|
||||||
|
|
||||||
class TestBaseSsync(BaseTest):
|
class TestBaseSsync(BaseTest):
|
||||||
@ -47,6 +48,7 @@ class TestBaseSsync(BaseTest):
|
|||||||
about the final state of the sender and receiver diskfiles.
|
about the final state of the sender and receiver diskfiles.
|
||||||
"""
|
"""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
super(TestBaseSsync, self).setUp()
|
super(TestBaseSsync, self).setUp()
|
||||||
# rx side setup
|
# rx side setup
|
||||||
self.rx_testdir = os.path.join(self.tmpdir, 'tmp_test_ssync_receiver')
|
self.rx_testdir = os.path.join(self.tmpdir, 'tmp_test_ssync_receiver')
|
||||||
|
@ -35,7 +35,7 @@ from swift.obj.reconstructor import ObjectReconstructor
|
|||||||
|
|
||||||
from test import listen_zero, unit
|
from test import listen_zero, unit
|
||||||
from test.unit import (debug_logger, patch_policies, make_timestamp_iter,
|
from test.unit import (debug_logger, patch_policies, make_timestamp_iter,
|
||||||
mock_check_drive)
|
mock_check_drive, skip_if_no_xattrs)
|
||||||
from test.unit.obj.common import write_diskfile
|
from test.unit.obj.common import write_diskfile
|
||||||
|
|
||||||
|
|
||||||
@ -43,12 +43,11 @@ from test.unit.obj.common import write_diskfile
|
|||||||
class TestReceiver(unittest.TestCase):
|
class TestReceiver(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
utils.HASH_PATH_SUFFIX = 'endcap'
|
utils.HASH_PATH_SUFFIX = 'endcap'
|
||||||
utils.HASH_PATH_PREFIX = 'startcap'
|
utils.HASH_PATH_PREFIX = 'startcap'
|
||||||
# Not sure why the test.unit stuff isn't taking effect here; so I'm
|
# Not sure why the test.unit stuff isn't taking effect here; so I'm
|
||||||
# reinforcing it.
|
# reinforcing it.
|
||||||
diskfile.getxattr = unit._getxattr
|
|
||||||
diskfile.setxattr = unit._setxattr
|
|
||||||
self.testdir = os.path.join(
|
self.testdir = os.path.join(
|
||||||
tempfile.mkdtemp(), 'tmp_test_ssync_receiver')
|
tempfile.mkdtemp(), 'tmp_test_ssync_receiver')
|
||||||
utils.mkdirs(os.path.join(self.testdir, 'sda1', 'tmp'))
|
utils.mkdirs(os.path.join(self.testdir, 'sda1', 'tmp'))
|
||||||
@ -1963,6 +1962,7 @@ class TestSsyncRxServer(unittest.TestCase):
|
|||||||
# server socket.
|
# server socket.
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
# dirs
|
# dirs
|
||||||
self.tmpdir = tempfile.mkdtemp()
|
self.tmpdir = tempfile.mkdtemp()
|
||||||
self.tempdir = os.path.join(self.tmpdir, 'tmp_test_obj_server')
|
self.tempdir = os.path.join(self.tmpdir, 'tmp_test_obj_server')
|
||||||
|
@ -26,8 +26,9 @@ from swift.common.utils import Timestamp
|
|||||||
from swift.obj import ssync_sender, diskfile, ssync_receiver
|
from swift.obj import ssync_sender, diskfile, ssync_receiver
|
||||||
from swift.obj.replicator import ObjectReplicator
|
from swift.obj.replicator import ObjectReplicator
|
||||||
|
|
||||||
from test.unit import patch_policies, make_timestamp_iter, debug_logger
|
|
||||||
from test.unit.obj.common import BaseTest
|
from test.unit.obj.common import BaseTest
|
||||||
|
from test.unit import patch_policies, make_timestamp_iter, skip_if_no_xattrs, \
|
||||||
|
debug_logger
|
||||||
|
|
||||||
|
|
||||||
class NullBufferedHTTPConnection(object):
|
class NullBufferedHTTPConnection(object):
|
||||||
@ -84,6 +85,7 @@ class FakeConnection(object):
|
|||||||
class TestSender(BaseTest):
|
class TestSender(BaseTest):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
super(TestSender, self).setUp()
|
super(TestSender, self).setUp()
|
||||||
self.daemon = ObjectReplicator(self.daemon_conf,
|
self.daemon = ObjectReplicator(self.daemon_conf,
|
||||||
debug_logger('test-ssync-sender'))
|
debug_logger('test-ssync-sender'))
|
||||||
|
@ -53,7 +53,8 @@ from test import listen_zero
|
|||||||
from test.unit import (
|
from test.unit import (
|
||||||
connect_tcp, readuntil2crlfs, FakeLogger, fake_http_connect, FakeRing,
|
connect_tcp, readuntil2crlfs, FakeLogger, fake_http_connect, FakeRing,
|
||||||
FakeMemcache, debug_logger, patch_policies, write_fake_ring,
|
FakeMemcache, debug_logger, patch_policies, write_fake_ring,
|
||||||
mocked_http_conn, DEFAULT_TEST_EC_TYPE, make_timestamp_iter)
|
mocked_http_conn, DEFAULT_TEST_EC_TYPE, make_timestamp_iter,
|
||||||
|
skip_if_no_xattrs)
|
||||||
from test.unit.helpers import setup_servers, teardown_servers
|
from test.unit.helpers import setup_servers, teardown_servers
|
||||||
from swift.proxy import server as proxy_server
|
from swift.proxy import server as proxy_server
|
||||||
from swift.proxy.controllers.obj import ReplicatedObjectController
|
from swift.proxy.controllers.obj import ReplicatedObjectController
|
||||||
@ -237,6 +238,7 @@ def _limit_max_file_size(f):
|
|||||||
class TestController(unittest.TestCase):
|
class TestController(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.account_ring = FakeRing()
|
self.account_ring = FakeRing()
|
||||||
self.container_ring = FakeRing()
|
self.container_ring = FakeRing()
|
||||||
self.memcache = FakeMemcache()
|
self.memcache = FakeMemcache()
|
||||||
@ -1288,6 +1290,7 @@ class TestProxyServerLoading(unittest.TestCase):
|
|||||||
class TestProxyServerConfigLoading(unittest.TestCase):
|
class TestProxyServerConfigLoading(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.tempdir = mkdtemp()
|
self.tempdir = mkdtemp()
|
||||||
account_ring_path = os.path.join(self.tempdir, 'account.ring.gz')
|
account_ring_path = os.path.join(self.tempdir, 'account.ring.gz')
|
||||||
write_fake_ring(account_ring_path)
|
write_fake_ring(account_ring_path)
|
||||||
@ -1987,6 +1990,7 @@ class TestReplicatedObjectController(
|
|||||||
Test suite for replication policy
|
Test suite for replication policy
|
||||||
"""
|
"""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.app = proxy_server.Application(
|
self.app = proxy_server.Application(
|
||||||
None, FakeMemcache(),
|
None, FakeMemcache(),
|
||||||
logger=debug_logger('proxy-ut'),
|
logger=debug_logger('proxy-ut'),
|
||||||
@ -6383,6 +6387,7 @@ class BaseTestECObjectController(BaseTestObjectController):
|
|||||||
|
|
||||||
class TestECObjectController(BaseTestECObjectController, unittest.TestCase):
|
class TestECObjectController(BaseTestECObjectController, unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.ec_policy = POLICIES[3]
|
self.ec_policy = POLICIES[3]
|
||||||
super(TestECObjectController, self).setUp()
|
super(TestECObjectController, self).setUp()
|
||||||
|
|
||||||
@ -6390,11 +6395,15 @@ class TestECObjectController(BaseTestECObjectController, unittest.TestCase):
|
|||||||
class TestECDuplicationObjectController(
|
class TestECDuplicationObjectController(
|
||||||
BaseTestECObjectController, unittest.TestCase):
|
BaseTestECObjectController, unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.ec_policy = POLICIES[4]
|
self.ec_policy = POLICIES[4]
|
||||||
super(TestECDuplicationObjectController, self).setUp()
|
super(TestECDuplicationObjectController, self).setUp()
|
||||||
|
|
||||||
|
|
||||||
class TestECMismatchedFA(unittest.TestCase):
|
class TestECMismatchedFA(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
prosrv = _test_servers[0]
|
prosrv = _test_servers[0]
|
||||||
# don't leak error limits and poison other tests
|
# don't leak error limits and poison other tests
|
||||||
@ -6581,6 +6590,7 @@ class TestECMismatchedFA(unittest.TestCase):
|
|||||||
class TestECGets(unittest.TestCase):
|
class TestECGets(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestECGets, self).setUp()
|
super(TestECGets, self).setUp()
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.tempdir = mkdtemp()
|
self.tempdir = mkdtemp()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
@ -6852,6 +6862,7 @@ class TestObjectDisconnectCleanup(unittest.TestCase):
|
|||||||
mkdirs(data_path)
|
mkdirs(data_path)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
debug.hub_exceptions(False)
|
debug.hub_exceptions(False)
|
||||||
self._cleanup_devices()
|
self._cleanup_devices()
|
||||||
|
|
||||||
@ -6960,6 +6971,7 @@ class TestObjectECRangedGET(unittest.TestCase):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
|
skip_if_no_xattrs()
|
||||||
cls.obj_name = 'range-get-test'
|
cls.obj_name = 'range-get-test'
|
||||||
cls.tiny_obj_name = 'range-get-test-tiny'
|
cls.tiny_obj_name = 'range-get-test-tiny'
|
||||||
cls.aligned_obj_name = 'range-get-test-aligned'
|
cls.aligned_obj_name = 'range-get-test-aligned'
|
||||||
@ -9488,6 +9500,7 @@ class TestProxyObjectPerformance(unittest.TestCase):
|
|||||||
# This is just a simple test that can be used to verify and debug the
|
# This is just a simple test that can be used to verify and debug the
|
||||||
# various data paths between the proxy server and the object
|
# various data paths between the proxy server and the object
|
||||||
# server. Used as a play ground to debug buffer sizes for sockets.
|
# server. Used as a play ground to debug buffer sizes for sockets.
|
||||||
|
skip_if_no_xattrs()
|
||||||
prolis = _test_sockets[0]
|
prolis = _test_sockets[0]
|
||||||
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
|
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
|
||||||
# Client is transmitting in 2 MB chunks
|
# Client is transmitting in 2 MB chunks
|
||||||
@ -9601,6 +9614,7 @@ class TestSocketObjectVersions(unittest.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
global _test_sockets
|
global _test_sockets
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.prolis = prolis = listen_zero()
|
self.prolis = prolis = listen_zero()
|
||||||
self._orig_prolis = _test_sockets[0]
|
self._orig_prolis = _test_sockets[0]
|
||||||
allowed_headers = ', '.join([
|
allowed_headers = ', '.join([
|
||||||
|
@ -30,7 +30,7 @@ from swift.proxy import server as proxy
|
|||||||
import swift.proxy.controllers
|
import swift.proxy.controllers
|
||||||
from swift.proxy.controllers.base import get_object_info
|
from swift.proxy.controllers.base import get_object_info
|
||||||
from test.unit import FakeMemcache, debug_logger, FakeRing, \
|
from test.unit import FakeMemcache, debug_logger, FakeRing, \
|
||||||
fake_http_connect, patch_policies
|
fake_http_connect, patch_policies, skip_if_no_xattrs
|
||||||
|
|
||||||
|
|
||||||
class FakeServerConnection(WSGIContext):
|
class FakeServerConnection(WSGIContext):
|
||||||
@ -132,6 +132,7 @@ class TestObjectSysmeta(unittest.TestCase):
|
|||||||
% (key, resp.headers))
|
% (key, resp.headers))
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
skip_if_no_xattrs()
|
||||||
self.app = proxy.Application(None, FakeMemcache(),
|
self.app = proxy.Application(None, FakeMemcache(),
|
||||||
logger=debug_logger('proxy-ut'),
|
logger=debug_logger('proxy-ut'),
|
||||||
account_ring=FakeRing(replicas=1),
|
account_ring=FakeRing(replicas=1),
|
||||||
|
Loading…
Reference in New Issue
Block a user