Support Storage Policy

* The file path on mountpoint was /container/obj and has been changed to
  /account/container/obj. This structure is not created on account and
  container creation but rather during the first object PUT to that
  container.
* Rename OnDiskManager class to DiskFileManager
* Remove overridden container_update() method and use Swift's default
  implementation that updates container DB.
* Add support for async_dir in storage policies - failed database
  updates are stored in these directories to be later picked up by
  object-updater daemon. This change reintroduced write_pickle and
  pickle_async_update methods which are slightly modified versions
  of Swift's methods of the same name.
* Updated tox.ini dependency on Swift to point to feature/ec branch of
  Swift's github repo.

Signed-off-by: Prashanth Pai <ppai@redhat.com>
This commit is contained in:
Prashanth Pai 2014-05-28 12:54:37 +05:30
parent ba39ade716
commit 3f4d0f98de
5 changed files with 144 additions and 68 deletions

View File

@ -16,6 +16,7 @@
import os import os
import stat import stat
import errno import errno
import random
import logging import logging
from hashlib import md5 from hashlib import md5
from eventlet import sleep from eventlet import sleep
@ -25,7 +26,7 @@ from swift.common.exceptions import DiskFileNoSpace
from gluster.swift.common.fs_utils import do_getctime, do_getmtime, do_stat, \ from gluster.swift.common.fs_utils import do_getctime, do_getmtime, do_stat, \
do_listdir, do_walk, do_rmdir, do_log_rl, get_filename_from_fd, do_open, \ do_listdir, do_walk, do_rmdir, do_log_rl, get_filename_from_fd, do_open, \
do_isdir, do_getsize, do_getxattr, do_setxattr, do_removexattr, do_read, \ do_isdir, do_getsize, do_getxattr, do_setxattr, do_removexattr, do_read, \
do_close, do_dup, do_lseek, do_fstat do_close, do_dup, do_lseek, do_fstat, do_fsync, do_rename
from gluster.swift.common import Glusterfs from gluster.swift.common import Glusterfs
X_CONTENT_TYPE = 'Content-Type' X_CONTENT_TYPE = 'Content-Type'
@ -530,3 +531,41 @@ def rmobjdir(dir_path):
raise raise
else: else:
return True return True
def write_pickle(obj, dest, tmp=None, pickle_protocol=0):
"""
Ensure that a pickle file gets written to disk. The file is first written
to a tmp file location in the destination directory path, ensured it is
synced to disk, then moved to its final destination name.
This version takes advantage of Gluster's dot-prefix-dot-suffix naming
where the a file named ".thefile.name.9a7aasv" is hashed to the same
Gluster node as "thefile.name". This ensures the renaming of a temp file
once written does not move it to another Gluster node.
:param obj: python object to be pickled
:param dest: path of final destination file
:param tmp: path to tmp to use, defaults to None (ignored)
:param pickle_protocol: protocol to pickle the obj with, defaults to 0
"""
dirname = os.path.dirname(dest)
# Create destination directory
try:
os.makedirs(dirname)
except OSError as err:
if err.errno != errno.EEXIST:
raise
basename = os.path.basename(dest)
tmpname = '.' + basename + '.' + \
md5(basename + str(random.random())).hexdigest()
tmppath = os.path.join(dirname, tmpname)
with open(tmppath, 'wb') as fo:
pickle.dump(obj, fo, pickle_protocol)
# TODO: This flush() method call turns into a flush() system call
# We'll need to wrap this as well, but we would do this by writing
# a context manager for our own open() method which returns an object
# in fo which makes the gluster API call.
fo.flush()
do_fsync(fo)
do_rename(tmppath, dest)

View File

@ -31,7 +31,8 @@ from greenlet import getcurrent
from contextlib import contextmanager from contextlib import contextmanager
from gluster.swift.common.exceptions import AlreadyExistsAsFile, \ from gluster.swift.common.exceptions import AlreadyExistsAsFile, \
AlreadyExistsAsDir AlreadyExistsAsDir
from swift.common.utils import TRUE_VALUES, ThreadPool, config_true_value from swift.common.utils import TRUE_VALUES, ThreadPool, config_true_value, \
hash_path, normalize_timestamp
from swift.common.exceptions import DiskFileNotExist, DiskFileError, \ from swift.common.exceptions import DiskFileNotExist, DiskFileError, \
DiskFileNoSpace, DiskFileDeviceUnavailable, DiskFileNotOpen, \ DiskFileNoSpace, DiskFileDeviceUnavailable, DiskFileNotOpen, \
DiskFileExpired DiskFileExpired
@ -44,12 +45,14 @@ from gluster.swift.common.fs_utils import do_fstat, do_open, do_close, \
do_fadvise64, do_rename, do_fdatasync, do_lseek, do_mkdir do_fadvise64, do_rename, do_fdatasync, do_lseek, do_mkdir
from gluster.swift.common.utils import read_metadata, write_metadata, \ from gluster.swift.common.utils import read_metadata, write_metadata, \
validate_object, create_object_metadata, rmobjdir, dir_is_object, \ validate_object, create_object_metadata, rmobjdir, dir_is_object, \
get_object_metadata get_object_metadata, write_pickle
from gluster.swift.common.utils import X_CONTENT_TYPE, \ from gluster.swift.common.utils import X_CONTENT_TYPE, \
X_TIMESTAMP, X_TYPE, X_OBJECT_TYPE, FILE, OBJECT, DIR_TYPE, \ X_TIMESTAMP, X_TYPE, X_OBJECT_TYPE, FILE, OBJECT, DIR_TYPE, \
FILE_TYPE, DEFAULT_UID, DEFAULT_GID, DIR_NON_OBJECT, DIR_OBJECT, \ FILE_TYPE, DEFAULT_UID, DEFAULT_GID, DIR_NON_OBJECT, DIR_OBJECT, \
X_ETAG, X_CONTENT_LENGTH X_ETAG, X_CONTENT_LENGTH
from ConfigParser import ConfigParser, NoSectionError, NoOptionError from ConfigParser import ConfigParser, NoSectionError, NoOptionError
from swift.common.storage_policy import get_policy_string
from functools import partial
# FIXME: Hopefully we'll be able to move to Python 2.7+ where O_CLOEXEC will # FIXME: Hopefully we'll be able to move to Python 2.7+ where O_CLOEXEC will
# be back ported. See http://www.python.org/dev/peps/pep-0433/ # be back ported. See http://www.python.org/dev/peps/pep-0433/
@ -67,6 +70,9 @@ MAX_OPEN_ATTEMPTS = 10
_cur_pid = str(os.getpid()) _cur_pid = str(os.getpid())
_cur_host = str(gethostname()) _cur_host = str(gethostname())
ASYNCDIR_BASE = 'async_pending'
get_async_dir = partial(get_policy_string, ASYNCDIR_BASE)
def _random_sleep(): def _random_sleep():
sleep(random.uniform(0.5, 0.15)) sleep(random.uniform(0.5, 0.15))
@ -223,7 +229,7 @@ def _adjust_metadata(metadata):
return metadata return metadata
class OnDiskManager(object): class DiskFileManager(object):
""" """
Management class for devices, providing common place for shared parameters Management class for devices, providing common place for shared parameters
and methods not provided by the DiskFile class (which primarily services and methods not provided by the DiskFile class (which primarily services
@ -254,6 +260,15 @@ class OnDiskManager(object):
self.threadpools = defaultdict( self.threadpools = defaultdict(
lambda: ThreadPool(nthreads=threads_per_disk)) lambda: ThreadPool(nthreads=threads_per_disk))
def construct_dev_path(self, device):
"""
Construct the path to a device without checking if it is mounted.
:param device: name of target device
:returns: full path to the device
"""
return os.path.join(self.devices, device)
def _get_dev_path(self, device): def _get_dev_path(self, device):
""" """
Return the path to a device, checking to see that it is a proper mount Return the path to a device, checking to see that it is a proper mount
@ -270,13 +285,26 @@ class OnDiskManager(object):
return dev_path return dev_path
def get_diskfile(self, device, account, container, obj, def get_diskfile(self, device, account, container, obj,
**kwargs): policy_idx=0, **kwargs):
dev_path = self._get_dev_path(device) dev_path = self._get_dev_path(device)
if not dev_path: if not dev_path:
raise DiskFileDeviceUnavailable() raise DiskFileDeviceUnavailable()
return DiskFile(self, dev_path, self.threadpools[device], return DiskFile(self, dev_path, self.threadpools[device],
account, container, obj, **kwargs) account, container, obj, **kwargs)
def pickle_async_update(self, device, account, container, obj, data,
timestamp, policy_idx):
device_path = self.construct_dev_path(device)
async_dir = os.path.join(device_path, get_async_dir(policy_idx))
ohash = hash_path(account, container, obj)
self.threadpools[device].run_in_thread(
write_pickle,
data,
os.path.join(async_dir, ohash[-3:], ohash + '-' +
normalize_timestamp(timestamp)),
os.path.join(device_path, 'tmp'))
self.logger.increment('async_pendings')
class DiskFileWriter(object): class DiskFileWriter(object):
""" """
@ -607,7 +635,15 @@ class DiskFile(object):
# Don't store a value for data_file until we know it exists. # Don't store a value for data_file until we know it exists.
self._data_file = None self._data_file = None
self._container_path = os.path.join(self._device_path, container) if not hasattr(self._mgr, 'reseller_prefix'):
self._mgr.reseller_prefix = 'AUTH_'
if account.startswith(self._mgr.reseller_prefix):
account = account[len(self._mgr.reseller_prefix):]
self._account = account
self._container = container
self._container_path = \
os.path.join(self._device_path, self._account, self._container)
obj = obj.strip(os.path.sep) obj = obj.strip(os.path.sep)
obj_path, self._obj = os.path.split(obj) obj_path, self._obj = os.path.split(obj)
if obj_path: if obj_path:
@ -862,6 +898,13 @@ class DiskFile(object):
:raises AlreadyExistsAsFile: if path or part of a path is not a \ :raises AlreadyExistsAsFile: if path or part of a path is not a \
directory directory
""" """
# Create /account/container directory structure on mount point root
try:
os.makedirs(self._container_path)
except OSError as err:
if err.errno != errno.EEXIST:
raise
data_file = os.path.join(self._put_datadir, self._obj) data_file = os.path.join(self._put_datadir, self._obj)
# Assume the full directory path exists to the file already, and # Assume the full directory path exists to the file already, and

View File

@ -26,7 +26,7 @@ from swift.common.request_helpers import split_and_validate_path
from swift.obj import server from swift.obj import server
from gluster.swift.obj.diskfile import OnDiskManager from gluster.swift.obj.diskfile import DiskFileManager
class ObjectController(server.ObjectController): class ObjectController(server.ObjectController):
@ -46,11 +46,12 @@ class ObjectController(server.ObjectController):
""" """
# Common on-disk hierarchy shared across account, container and object # Common on-disk hierarchy shared across account, container and object
# servers. # servers.
self._ondisk_mgr = OnDiskManager(conf, self.logger) self._diskfile_mgr = DiskFileManager(conf, self.logger)
self.swift_dir = conf.get('swift_dir', '/etc/swift') self._diskfile_mgr.reseller_prefix = \
conf.get('reseller_prefix', 'AUTH_').strip()
def get_diskfile(self, device, partition, account, container, obj, def get_diskfile(self, device, partition, account, container, obj,
**kwargs): policy_idx=0, **kwargs):
""" """
Utility method for instantiating a DiskFile object supporting a given Utility method for instantiating a DiskFile object supporting a given
REST API. REST API.
@ -59,17 +60,8 @@ class ObjectController(server.ObjectController):
DiskFile class would simply over-ride this method to provide that DiskFile class would simply over-ride this method to provide that
behavior. behavior.
""" """
return self._ondisk_mgr.get_diskfile(device, account, container, obj, return self._diskfile_mgr.get_diskfile(device, account, container, obj,
**kwargs) **kwargs)
def container_update(self, *args, **kwargs):
"""
Update the container when objects are updated.
For Gluster, this is just a no-op, since a container is just the
directory holding all the objects (sub-directory hierarchy of files).
"""
return
@public @public
@timing_stats() @timing_stats()

View File

@ -36,7 +36,7 @@ from gluster.swift.common.exceptions import GlusterFileSystemOSError
import gluster.swift.common.utils import gluster.swift.common.utils
from gluster.swift.common.utils import normalize_timestamp from gluster.swift.common.utils import normalize_timestamp
import gluster.swift.obj.diskfile import gluster.swift.obj.diskfile
from gluster.swift.obj.diskfile import DiskFileWriter, DiskFile, OnDiskManager from gluster.swift.obj.diskfile import DiskFileWriter, DiskFile, DiskFileManager
from gluster.swift.common.utils import DEFAULT_UID, DEFAULT_GID, X_TYPE, \ from gluster.swift.common.utils import DEFAULT_UID, DEFAULT_GID, X_TYPE, \
X_OBJECT_TYPE, DIR_OBJECT X_OBJECT_TYPE, DIR_OBJECT
@ -136,7 +136,7 @@ class TestDiskFile(unittest.TestCase):
self.td = tempfile.mkdtemp() self.td = tempfile.mkdtemp()
self.conf = dict(devices=self.td, mb_per_sync=2, self.conf = dict(devices=self.td, mb_per_sync=2,
keep_cache_size=(1024 * 1024), mount_check=False) keep_cache_size=(1024 * 1024), mount_check=False)
self.mgr = OnDiskManager(self.conf, self.lg) self.mgr = DiskFileManager(self.conf, self.lg)
def tearDown(self): def tearDown(self):
tpool.execute = self._orig_tpool_exc tpool.execute = self._orig_tpool_exc
@ -161,9 +161,9 @@ class TestDiskFile(unittest.TestCase):
assert gdf._gid == DEFAULT_GID assert gdf._gid == DEFAULT_GID
assert gdf._obj == "z" assert gdf._obj == "z"
assert gdf._obj_path == "" assert gdf._obj_path == ""
assert gdf._datadir == os.path.join(self.td, "vol0", "bar"), gdf._datadir assert gdf._datadir == os.path.join(self.td, "vol0", "ufo47", "bar"), gdf._datadir
assert gdf._datadir == gdf._put_datadir assert gdf._datadir == gdf._put_datadir
assert gdf._data_file == os.path.join(self.td, "vol0", "bar", "z") assert gdf._data_file == os.path.join(self.td, "vol0", "ufo47", "bar", "z")
assert gdf._is_dir is False assert gdf._is_dir is False
assert gdf._logger == self.lg assert gdf._logger == self.lg
assert gdf._fd is None assert gdf._fd is None
@ -172,10 +172,10 @@ class TestDiskFile(unittest.TestCase):
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "/b/a/z/") gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "/b/a/z/")
assert gdf._obj == "z" assert gdf._obj == "z"
assert gdf._obj_path == "b/a" assert gdf._obj_path == "b/a"
assert gdf._datadir == os.path.join(self.td, "vol0", "bar", "b", "a"), gdf._datadir assert gdf._datadir == os.path.join(self.td, "vol0", "ufo47", "bar", "b", "a"), gdf._datadir
def test_open_no_metadata(self): def test_open_no_metadata(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_file = os.path.join(the_path, "z") the_file = os.path.join(the_path, "z")
os.makedirs(the_path) os.makedirs(the_path)
with open(the_file, "wb") as fd: with open(the_file, "wb") as fd:
@ -215,7 +215,7 @@ class TestDiskFile(unittest.TestCase):
self.assertTrue(mock_close.called) self.assertTrue(mock_close.called)
def test_open_existing_metadata(self): def test_open_existing_metadata(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_file = os.path.join(the_path, "z") the_file = os.path.join(the_path, "z")
os.makedirs(the_path) os.makedirs(the_path)
with open(the_file, "wb") as fd: with open(the_file, "wb") as fd:
@ -243,7 +243,7 @@ class TestDiskFile(unittest.TestCase):
assert gdf._metadata == exp_md, "%r != %r" % (gdf._metadata, exp_md) assert gdf._metadata == exp_md, "%r != %r" % (gdf._metadata, exp_md)
def test_open_invalid_existing_metadata(self): def test_open_invalid_existing_metadata(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_file = os.path.join(the_path, "z") the_file = os.path.join(the_path, "z")
os.makedirs(the_path) os.makedirs(the_path)
with open(the_file, "wb") as fd: with open(the_file, "wb") as fd:
@ -263,7 +263,7 @@ class TestDiskFile(unittest.TestCase):
assert gdf._metadata != inv_md assert gdf._metadata != inv_md
def test_open_isdir(self): def test_open_isdir(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_dir = os.path.join(the_path, "d") the_dir = os.path.join(the_path, "d")
os.makedirs(the_dir) os.makedirs(the_dir)
ini_md = { ini_md = {
@ -287,7 +287,7 @@ class TestDiskFile(unittest.TestCase):
def _create_and_get_diskfile(self, dev, par, acc, con, obj, fsize=256): def _create_and_get_diskfile(self, dev, par, acc, con, obj, fsize=256):
# FIXME: assumes account === volume # FIXME: assumes account === volume
the_path = os.path.join(self.td, dev, con) the_path = os.path.join(self.td, dev, acc, con)
the_file = os.path.join(the_path, obj) the_file = os.path.join(the_path, obj)
base_obj = os.path.basename(the_file) base_obj = os.path.basename(the_file)
base_dir = os.path.dirname(the_file) base_dir = os.path.dirname(the_file)
@ -312,7 +312,7 @@ class TestDiskFile(unittest.TestCase):
gdf = self._create_and_get_diskfile("vol0", "p57", "ufo47", "bar", "z") gdf = self._create_and_get_diskfile("vol0", "p57", "ufo47", "bar", "z")
with gdf.open(): with gdf.open():
assert gdf._fd is not None assert gdf._fd is not None
assert gdf._data_file == os.path.join(self.td, "vol0", "bar", "z") assert gdf._data_file == os.path.join(self.td, "vol0", "ufo47", "bar", "z")
reader = gdf.reader() reader = gdf.reader()
assert reader._fd is not None assert reader._fd is not None
fd[0] = reader._fd fd[0] = reader._fd
@ -324,7 +324,7 @@ class TestDiskFile(unittest.TestCase):
def test_reader_disk_chunk_size(self): def test_reader_disk_chunk_size(self):
conf = dict(disk_chunk_size=64) conf = dict(disk_chunk_size=64)
conf.update(self.conf) conf.update(self.conf)
self.mgr = OnDiskManager(conf, self.lg) self.mgr = DiskFileManager(conf, self.lg)
gdf = self._create_and_get_diskfile("vol0", "p57", "ufo47", "bar", "z") gdf = self._create_and_get_diskfile("vol0", "p57", "ufo47", "bar", "z")
with gdf.open(): with gdf.open():
reader = gdf.reader() reader = gdf.reader()
@ -365,7 +365,7 @@ class TestDiskFile(unittest.TestCase):
gdf = self._create_and_get_diskfile("vol0", "p57", "ufo47", "bar", "z", fsize=1024*1024*2) gdf = self._create_and_get_diskfile("vol0", "p57", "ufo47", "bar", "z", fsize=1024*1024*2)
with gdf.open(): with gdf.open():
assert gdf._fd is not None assert gdf._fd is not None
assert gdf._data_file == os.path.join(self.td, "vol0", "bar", "z") assert gdf._data_file == os.path.join(self.td, "vol0", "ufo47", "bar", "z")
reader = gdf.reader() reader = gdf.reader()
assert reader._fd is not None assert reader._fd is not None
fd[0] = reader._fd fd[0] = reader._fd
@ -380,7 +380,7 @@ class TestDiskFile(unittest.TestCase):
called[0] = True called[0] = True
os.close(fd) os.close(fd)
the_cont = os.path.join(self.td, "vol0", "bar") the_cont = os.path.join(self.td, "vol0", "ufo47", "bar")
os.makedirs(os.path.join(the_cont, "dir")) os.makedirs(os.path.join(the_cont, "dir"))
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir") gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir")
with gdf.open(): with gdf.open():
@ -396,7 +396,7 @@ class TestDiskFile(unittest.TestCase):
reader.close() reader.close()
def test_create_dir_object_no_md(self): def test_create_dir_object_no_md(self):
the_cont = os.path.join(self.td, "vol0", "bar") the_cont = os.path.join(self.td, "vol0", "ufo47", "bar")
the_dir = "dir" the_dir = "dir"
os.makedirs(the_cont) os.makedirs(the_cont)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar",
@ -409,7 +409,7 @@ class TestDiskFile(unittest.TestCase):
assert _mapit(full_dir_path) not in _metadata assert _mapit(full_dir_path) not in _metadata
def test_create_dir_object_with_md(self): def test_create_dir_object_with_md(self):
the_cont = os.path.join(self.td, "vol0", "bar") the_cont = os.path.join(self.td, "vol0", "ufo47", "bar")
the_dir = "dir" the_dir = "dir"
os.makedirs(the_cont) os.makedirs(the_cont)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar",
@ -468,7 +468,7 @@ class TestDiskFile(unittest.TestCase):
self.assertFalse(_mapit(the_dir) in _metadata) self.assertFalse(_mapit(the_dir) in _metadata)
def test_write_metadata(self): def test_write_metadata(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_dir = os.path.join(the_path, "z") the_dir = os.path.join(the_path, "z")
os.makedirs(the_dir) os.makedirs(the_dir)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z") gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
@ -481,7 +481,7 @@ class TestDiskFile(unittest.TestCase):
self.assertTrue(fmd['Content-Type'], md['Content-Type']) self.assertTrue(fmd['Content-Type'], md['Content-Type'])
def test_add_metadata_to_existing_file(self): def test_add_metadata_to_existing_file(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_file = os.path.join(the_path, "z") the_file = os.path.join(the_path, "z")
os.makedirs(the_path) os.makedirs(the_path)
with open(the_file, "wb") as fd: with open(the_file, "wb") as fd:
@ -509,7 +509,7 @@ class TestDiskFile(unittest.TestCase):
self.assertFalse('a' in on_disk_md) self.assertFalse('a' in on_disk_md)
def test_add_md_to_existing_file_with_md_in_gdf(self): def test_add_md_to_existing_file_with_md_in_gdf(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_file = os.path.join(the_path, "z") the_file = os.path.join(the_path, "z")
os.makedirs(the_path) os.makedirs(the_path)
with open(the_file, "wb") as fd: with open(the_file, "wb") as fd:
@ -537,7 +537,7 @@ class TestDiskFile(unittest.TestCase):
self.assertFalse('a' in on_disk_md) self.assertFalse('a' in on_disk_md)
def test_add_metadata_to_existing_dir(self): def test_add_metadata_to_existing_dir(self):
the_cont = os.path.join(self.td, "vol0", "bar") the_cont = os.path.join(self.td, "vol0", "ufo47", "bar")
the_dir = os.path.join(the_cont, "dir") the_dir = os.path.join(the_cont, "dir")
os.makedirs(the_dir) os.makedirs(the_dir)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir") gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir")
@ -571,7 +571,7 @@ class TestDiskFile(unittest.TestCase):
def test_write_metadata_w_meta_file(self): def test_write_metadata_w_meta_file(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_file = os.path.join(the_path, "z") the_file = os.path.join(the_path, "z")
os.makedirs(the_path) os.makedirs(the_path)
with open(the_file, "wb") as fd: with open(the_file, "wb") as fd:
@ -583,7 +583,7 @@ class TestDiskFile(unittest.TestCase):
assert _metadata[_mapit(the_file)] == newmd assert _metadata[_mapit(the_file)] == newmd
def test_write_metadata_w_meta_file_no_content_type(self): def test_write_metadata_w_meta_file_no_content_type(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_file = os.path.join(the_path, "z") the_file = os.path.join(the_path, "z")
os.makedirs(the_path) os.makedirs(the_path)
with open(the_file, "wb") as fd: with open(the_file, "wb") as fd:
@ -596,7 +596,7 @@ class TestDiskFile(unittest.TestCase):
assert _metadata[_mapit(the_file)] == newmd assert _metadata[_mapit(the_file)] == newmd
def test_write_metadata_w_meta_dir(self): def test_write_metadata_w_meta_dir(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_dir = os.path.join(the_path, "dir") the_dir = os.path.join(the_path, "dir")
os.makedirs(the_dir) os.makedirs(the_dir)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir") gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir")
@ -606,7 +606,7 @@ class TestDiskFile(unittest.TestCase):
assert _metadata[_mapit(the_dir)] == newmd assert _metadata[_mapit(the_dir)] == newmd
def test_write_metadata_w_marker_dir(self): def test_write_metadata_w_marker_dir(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_dir = os.path.join(the_path, "dir") the_dir = os.path.join(the_path, "dir")
os.makedirs(the_dir) os.makedirs(the_dir)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir") gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir")
@ -616,7 +616,7 @@ class TestDiskFile(unittest.TestCase):
assert _metadata[_mapit(the_dir)] == newmd assert _metadata[_mapit(the_dir)] == newmd
def test_put_w_marker_dir_create(self): def test_put_w_marker_dir_create(self):
the_cont = os.path.join(self.td, "vol0", "bar") the_cont = os.path.join(self.td, "vol0", "ufo47", "bar")
the_dir = os.path.join(the_cont, "dir") the_dir = os.path.join(the_cont, "dir")
os.makedirs(the_cont) os.makedirs(the_cont)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir") gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir")
@ -633,7 +633,7 @@ class TestDiskFile(unittest.TestCase):
assert _metadata[_mapit(the_dir)][X_OBJECT_TYPE] == DIR_OBJECT assert _metadata[_mapit(the_dir)][X_OBJECT_TYPE] == DIR_OBJECT
def test_put_is_dir(self): def test_put_is_dir(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_dir = os.path.join(the_path, "dir") the_dir = os.path.join(the_path, "dir")
os.makedirs(the_dir) os.makedirs(the_dir)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir") gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir")
@ -664,14 +664,14 @@ class TestDiskFile(unittest.TestCase):
origfmd, _metadata[_mapit(the_dir)]) origfmd, _metadata[_mapit(the_dir)])
def test_put(self): def test_put(self):
the_cont = os.path.join(self.td, "vol0", "bar") the_cont = os.path.join(self.td, "vol0", "ufo47", "bar")
os.makedirs(the_cont) os.makedirs(the_cont)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z") gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
assert gdf._obj == "z" assert gdf._obj == "z"
assert gdf._obj_path == "" assert gdf._obj_path == ""
assert gdf._container_path == os.path.join(self.td, "vol0", "bar") assert gdf._container_path == os.path.join(self.td, "vol0", "ufo47", "bar")
assert gdf._datadir == the_cont assert gdf._datadir == the_cont
assert gdf._data_file == os.path.join(self.td, "vol0", "bar", "z") assert gdf._data_file == os.path.join(self.td, "vol0", "ufo47", "bar", "z")
body = '1234\n' body = '1234\n'
etag = md5() etag = md5()
@ -694,14 +694,14 @@ class TestDiskFile(unittest.TestCase):
assert not os.path.exists(tmppath) assert not os.path.exists(tmppath)
def test_put_ENOSPC(self): def test_put_ENOSPC(self):
the_cont = os.path.join(self.td, "vol0", "bar") the_cont = os.path.join(self.td, "vol0", "ufo47", "bar")
os.makedirs(the_cont) os.makedirs(the_cont)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z") gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
assert gdf._obj == "z" assert gdf._obj == "z"
assert gdf._obj_path == "" assert gdf._obj_path == ""
assert gdf._container_path == os.path.join(self.td, "vol0", "bar") assert gdf._container_path == os.path.join(self.td, "vol0", "ufo47", "bar")
assert gdf._datadir == the_cont assert gdf._datadir == the_cont
assert gdf._data_file == os.path.join(self.td, "vol0", "bar", "z") assert gdf._data_file == os.path.join(self.td, "vol0", "ufo47", "bar", "z")
body = '1234\n' body = '1234\n'
etag = md5() etag = md5()
@ -729,14 +729,14 @@ class TestDiskFile(unittest.TestCase):
self.fail("Expected exception DiskFileNoSpace") self.fail("Expected exception DiskFileNoSpace")
def test_put_rename_ENOENT(self): def test_put_rename_ENOENT(self):
the_cont = os.path.join(self.td, "vol0", "bar") the_cont = os.path.join(self.td, "vol0", "ufo47", "bar")
os.makedirs(the_cont) os.makedirs(the_cont)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z") gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "z")
assert gdf._obj == "z" assert gdf._obj == "z"
assert gdf._obj_path == "" assert gdf._obj_path == ""
assert gdf._container_path == os.path.join(self.td, "vol0", "bar") assert gdf._container_path == os.path.join(self.td, "vol0", "ufo47", "bar")
assert gdf._datadir == the_cont assert gdf._datadir == the_cont
assert gdf._data_file == os.path.join(self.td, "vol0", "bar", "z") assert gdf._data_file == os.path.join(self.td, "vol0", "ufo47", "bar", "z")
body = '1234\n' body = '1234\n'
etag = md5() etag = md5()
@ -775,10 +775,10 @@ class TestDiskFile(unittest.TestCase):
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", the_file) gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", the_file)
assert gdf._obj == "z" assert gdf._obj == "z"
assert gdf._obj_path == the_obj_path assert gdf._obj_path == the_obj_path
assert gdf._container_path == os.path.join(self.td, "vol0", "bar") assert gdf._container_path == os.path.join(self.td, "vol0", "ufo47", "bar")
assert gdf._datadir == os.path.join(self.td, "vol0", "bar", "b", "a") assert gdf._datadir == os.path.join(self.td, "vol0", "ufo47", "bar", "b", "a")
assert gdf._data_file == os.path.join( assert gdf._data_file == os.path.join(
self.td, "vol0", "bar", "b", "a", "z") self.td, "vol0", "ufo47", "bar", "b", "a", "z")
body = '1234\n' body = '1234\n'
etag = md5() etag = md5()
@ -801,7 +801,7 @@ class TestDiskFile(unittest.TestCase):
assert not os.path.exists(tmppath) assert not os.path.exists(tmppath)
def test_delete(self): def test_delete(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_file = os.path.join(the_path, "z") the_file = os.path.join(the_path, "z")
os.makedirs(the_path) os.makedirs(the_path)
with open(the_file, "wb") as fd: with open(the_file, "wb") as fd:
@ -816,7 +816,7 @@ class TestDiskFile(unittest.TestCase):
assert not os.path.exists(os.path.join(gdf._datadir, gdf._obj)) assert not os.path.exists(os.path.join(gdf._datadir, gdf._obj))
def test_delete_same_timestamp(self): def test_delete_same_timestamp(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_file = os.path.join(the_path, "z") the_file = os.path.join(the_path, "z")
os.makedirs(the_path) os.makedirs(the_path)
with open(the_file, "wb") as fd: with open(the_file, "wb") as fd:
@ -831,7 +831,7 @@ class TestDiskFile(unittest.TestCase):
assert os.path.exists(os.path.join(gdf._datadir, gdf._obj)) assert os.path.exists(os.path.join(gdf._datadir, gdf._obj))
def test_delete_file_not_found(self): def test_delete_file_not_found(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_file = os.path.join(the_path, "z") the_file = os.path.join(the_path, "z")
os.makedirs(the_path) os.makedirs(the_path)
with open(the_file, "wb") as fd: with open(the_file, "wb") as fd:
@ -850,7 +850,7 @@ class TestDiskFile(unittest.TestCase):
assert not os.path.exists(os.path.join(gdf._datadir, gdf._obj)) assert not os.path.exists(os.path.join(gdf._datadir, gdf._obj))
def test_delete_file_unlink_error(self): def test_delete_file_unlink_error(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_file = os.path.join(the_path, "z") the_file = os.path.join(the_path, "z")
os.makedirs(the_path) os.makedirs(the_path)
with open(the_file, "wb") as fd: with open(the_file, "wb") as fd:
@ -884,7 +884,7 @@ class TestDiskFile(unittest.TestCase):
assert os.path.exists(os.path.join(gdf._datadir, gdf._obj)) assert os.path.exists(os.path.join(gdf._datadir, gdf._obj))
def test_delete_is_dir(self): def test_delete_is_dir(self):
the_path = os.path.join(self.td, "vol0", "bar") the_path = os.path.join(self.td, "vol0", "ufo47", "bar")
the_dir = os.path.join(the_path, "d") the_dir = os.path.join(the_path, "d")
os.makedirs(the_dir) os.makedirs(the_dir)
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "d") gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "d")
@ -899,7 +899,7 @@ class TestDiskFile(unittest.TestCase):
saved_tmppath = '' saved_tmppath = ''
saved_fd = None saved_fd = None
with gdf.create() as dw: with gdf.create() as dw:
assert gdf._datadir == os.path.join(self.td, "vol0", "bar", "dir") assert gdf._datadir == os.path.join(self.td, "vol0", "ufo47", "bar", "dir")
assert os.path.isdir(gdf._datadir) assert os.path.isdir(gdf._datadir)
saved_tmppath = dw._tmppath saved_tmppath = dw._tmppath
assert os.path.dirname(saved_tmppath) == gdf._datadir assert os.path.dirname(saved_tmppath) == gdf._datadir
@ -922,7 +922,7 @@ class TestDiskFile(unittest.TestCase):
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir/z") gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir/z")
saved_tmppath = '' saved_tmppath = ''
with gdf.create() as dw: with gdf.create() as dw:
assert gdf._datadir == os.path.join(self.td, "vol0", "bar", "dir") assert gdf._datadir == os.path.join(self.td, "vol0", "ufo47", "bar", "dir")
assert os.path.isdir(gdf._datadir) assert os.path.isdir(gdf._datadir)
saved_tmppath = dw._tmppath saved_tmppath = dw._tmppath
assert os.path.dirname(saved_tmppath) == gdf._datadir assert os.path.dirname(saved_tmppath) == gdf._datadir
@ -937,7 +937,7 @@ class TestDiskFile(unittest.TestCase):
gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir/z") gdf = self._get_diskfile("vol0", "p57", "ufo47", "bar", "dir/z")
saved_tmppath = '' saved_tmppath = ''
with gdf.create() as dw: with gdf.create() as dw:
assert gdf._datadir == os.path.join(self.td, "vol0", "bar", "dir") assert gdf._datadir == os.path.join(self.td, "vol0", "ufo47", "bar", "dir")
assert os.path.isdir(gdf._datadir) assert os.path.isdir(gdf._datadir)
saved_tmppath = dw._tmppath saved_tmppath = dw._tmppath
assert os.path.dirname(saved_tmppath) == gdf._datadir assert os.path.dirname(saved_tmppath) == gdf._datadir

View File

@ -18,7 +18,9 @@ setenv = VIRTUAL_ENV={envdir}
NOSE_COVER_BRANCHES=1 NOSE_COVER_BRANCHES=1
NOSE_COVER_PACKAGE=gluster NOSE_COVER_PACKAGE=gluster
deps = deps =
https://launchpad.net/swift/icehouse/1.13.1/+download/swift-1.13.1.tar.gz # GitHub's .zip URL won't work! pip supports installing from git repos.
# https://pip.pypa.io/en/latest/reference/pip_install.html#git
git+https://github.com/openstack/swift.git@feature/ec
-r{toxinidir}/requirements.txt -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt -r{toxinidir}/test-requirements.txt
changedir = {toxinidir}/test/unit changedir = {toxinidir}/test/unit