3.3.1-4
Swift+UFO, now with less swift forkage. Specifically the only patches to swift are those already used for the Fedora openstack-swift packages _plus_ our backport of the upstream constraints config changes that have been accepted into grizzly.
This commit is contained in:
parent
fee29178fd
commit
fdd4bcfad0
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,4 +15,5 @@ glusterfs-3.2.7.tar.gz
|
|||||||
glusterfs-3.3.0.tar.gz
|
glusterfs-3.3.0.tar.gz
|
||||||
glusterfs-3.3.1.tar.gz
|
glusterfs-3.3.1.tar.gz
|
||||||
swift-1.4.8.tar.gz
|
swift-1.4.8.tar.gz
|
||||||
|
gluster-swift-ufo-1.1.tar.gz
|
||||||
*.src.rpm
|
*.src.rpm
|
||||||
|
518
glusterfs-3.3.1.swift.constraints.backport.patch
Normal file
518
glusterfs-3.3.1.swift.constraints.backport.patch
Normal file
@ -0,0 +1,518 @@
|
|||||||
|
From fc2421b04022ac6bbe9d5014362ec5f99f94c5e0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Peter Portante <peter.portante@redhat.com>
|
||||||
|
Date: Tue, 25 Sep 2012 13:27:59 -0400
|
||||||
|
Subject: [PATCH] Backport commit a2ac5efaa64f57fbbe059066c6c4636dfd0715c2,
|
||||||
|
'swift constraints are now settable via config', excluding
|
||||||
|
PEP8 changes that did not involve the constraints.
|
||||||
|
|
||||||
|
---
|
||||||
|
etc/swift.conf-sample | 73 ++++++++++++++++++++++++++++++++++
|
||||||
|
swift/common/constraints.py | 37 ++++++++++++-----
|
||||||
|
test/functional/tests.py | 62 ++++++++++++++++++++++++----
|
||||||
|
test/unit/common/test_constraints.py | 9 +++-
|
||||||
|
test/unit/obj/test_server.py | 7 ++-
|
||||||
|
test/unit/proxy/test_server.py | 50 ++++++++++++++---------
|
||||||
|
6 files changed, 196 insertions(+), 42 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/etc/swift.conf-sample b/etc/swift.conf-sample
|
||||||
|
index 7e1c31d..2f4192a 100644
|
||||||
|
--- a/etc/swift.conf-sample
|
||||||
|
+++ b/etc/swift.conf-sample
|
||||||
|
@@ -1,3 +1,76 @@
|
||||||
|
[swift-hash]
|
||||||
|
+
|
||||||
|
+# swift_hash_path_suffix is used as part of the hashing algorithm
|
||||||
|
+# when determining data placement in the cluster. This value should
|
||||||
|
+# remain secret and MUST NOT change once a cluster has been deployed.
|
||||||
|
+
|
||||||
|
swift_hash_path_suffix = changeme
|
||||||
|
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+# The swift-constraints section sets the basic constraints on data
|
||||||
|
+# saved in the swift cluster.
|
||||||
|
+
|
||||||
|
+[swift-constraints]
|
||||||
|
+
|
||||||
|
+# max_file_size is the largest "normal" object that can be saved in
|
||||||
|
+# the cluster. This is also the limit on the size of each segment of
|
||||||
|
+# a "large" object when using the large object manifest support.
|
||||||
|
+# This value is set in bytes. Setting it to lower than 1MiB will cause
|
||||||
|
+# some tests to fail. It is STRONGLY recommended to leave this value at
|
||||||
|
+# the default (5 * 2**30 + 2).
|
||||||
|
+
|
||||||
|
+#max_file_size = 5368709122
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+# max_meta_name_length is the max number of bytes in the utf8 encoding
|
||||||
|
+# of the name portion of a metadata header.
|
||||||
|
+
|
||||||
|
+#max_meta_name_length = 128
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+# max_meta_value_length is the max number of bytes in the utf8 encoding
|
||||||
|
+# of a metadata value
|
||||||
|
+
|
||||||
|
+#max_meta_value_length = 256
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+# max_meta_count is the max number of metadata keys that can be stored
|
||||||
|
+# on a single account, container, or object
|
||||||
|
+
|
||||||
|
+#max_meta_count = 90
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+# max_meta_overall_size is the max number of bytes in the utf8 encoding
|
||||||
|
+# of the metadata (keys + values)
|
||||||
|
+
|
||||||
|
+#max_meta_overall_size = 4096
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+# max_object_name_length is the max number of bytes in the utf8 encoding
|
||||||
|
+# of an object name
|
||||||
|
+
|
||||||
|
+#max_object_name_length = 1024
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+# container_listing_limit is the default (and max) number of items
|
||||||
|
+# returned for a container listing request
|
||||||
|
+
|
||||||
|
+#container_listing_limit = 10000
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+# account_listing_limit is the default (and max) number of items returned
|
||||||
|
+# for an account listing request
|
||||||
|
+#account_listing_limit = 10000
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+# max_account_name_length is the max number of bytes in the utf8 encoding
|
||||||
|
+# of an account name
|
||||||
|
+
|
||||||
|
+#max_account_name_length = 256
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+# max_container_name_length is the max number of bytes in the utf8 encoding
|
||||||
|
+# of a container name
|
||||||
|
+
|
||||||
|
+#max_container_name_length = 256
|
||||||
|
diff --git a/swift/common/constraints.py b/swift/common/constraints.py
|
||||||
|
index 235dcca..0fe5078 100644
|
||||||
|
--- a/swift/common/constraints.py
|
||||||
|
+++ b/swift/common/constraints.py
|
||||||
|
@@ -14,29 +14,46 @@
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
import os
|
||||||
|
+from ConfigParser import ConfigParser, NoSectionError, NoOptionError, \
|
||||||
|
+ RawConfigParser
|
||||||
|
|
||||||
|
from webob.exc import HTTPBadRequest, HTTPLengthRequired, \
|
||||||
|
HTTPRequestEntityTooLarge
|
||||||
|
|
||||||
|
+constraints_conf = ConfigParser()
|
||||||
|
+constraints_conf.read('/etc/swift/swift.conf')
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def constraints_conf_int(name, default):
|
||||||
|
+ try:
|
||||||
|
+ return int(constraints_conf.get('swift-constraints', name))
|
||||||
|
+ except (NoSectionError, NoOptionError):
|
||||||
|
+ return default
|
||||||
|
+
|
||||||
|
|
||||||
|
#: Max file size allowed for objects
|
||||||
|
-MAX_FILE_SIZE = 5 * 1024 * 1024 * 1024 + 2
|
||||||
|
+MAX_FILE_SIZE = constraints_conf_int('max_file_size',
|
||||||
|
+ 5368709122) # 5 * 1024 * 1024 * 1024 + 2
|
||||||
|
#: Max length of the name of a key for metadata
|
||||||
|
-MAX_META_NAME_LENGTH = 128
|
||||||
|
+MAX_META_NAME_LENGTH = constraints_conf_int('max_meta_name_length', 128)
|
||||||
|
#: Max length of the value of a key for metadata
|
||||||
|
-MAX_META_VALUE_LENGTH = 256
|
||||||
|
+MAX_META_VALUE_LENGTH = constraints_conf_int('max_meta_value_length', 256)
|
||||||
|
#: Max number of metadata items
|
||||||
|
-MAX_META_COUNT = 90
|
||||||
|
+MAX_META_COUNT = constraints_conf_int('max_meta_count', 90)
|
||||||
|
#: Max overall size of metadata
|
||||||
|
-MAX_META_OVERALL_SIZE = 4096
|
||||||
|
+MAX_META_OVERALL_SIZE = constraints_conf_int('max_meta_overall_size', 4096)
|
||||||
|
#: Max object name length
|
||||||
|
-MAX_OBJECT_NAME_LENGTH = 1024
|
||||||
|
+MAX_OBJECT_NAME_LENGTH = constraints_conf_int('max_object_name_length', 1024)
|
||||||
|
#: Max object list length of a get request for a container
|
||||||
|
-CONTAINER_LISTING_LIMIT = 10000
|
||||||
|
+CONTAINER_LISTING_LIMIT = constraints_conf_int('container_listing_limit',
|
||||||
|
+ 10000)
|
||||||
|
#: Max container list length of a get request for an account
|
||||||
|
-ACCOUNT_LISTING_LIMIT = 10000
|
||||||
|
-MAX_ACCOUNT_NAME_LENGTH = 256
|
||||||
|
-MAX_CONTAINER_NAME_LENGTH = 256
|
||||||
|
+ACCOUNT_LISTING_LIMIT = constraints_conf_int('account_listing_limit', 10000)
|
||||||
|
+#: Max account name length
|
||||||
|
+MAX_ACCOUNT_NAME_LENGTH = constraints_conf_int('max_account_name_length', 256)
|
||||||
|
+#: Max container name length
|
||||||
|
+MAX_CONTAINER_NAME_LENGTH = constraints_conf_int('max_container_name_length',
|
||||||
|
+ 256)
|
||||||
|
|
||||||
|
|
||||||
|
def check_metadata(req, target_type):
|
||||||
|
diff --git a/test/functional/tests.py b/test/functional/tests.py
|
||||||
|
index b25b4fd..3b18fc4 100644
|
||||||
|
--- a/test/functional/tests.py
|
||||||
|
+++ b/test/functional/tests.py
|
||||||
|
@@ -27,12 +27,55 @@ import threading
|
||||||
|
import uuid
|
||||||
|
import unittest
|
||||||
|
import urllib
|
||||||
|
+from ConfigParser import ConfigParser
|
||||||
|
|
||||||
|
from test import get_config
|
||||||
|
from swift import Account, AuthenticationFailed, Connection, Container, \
|
||||||
|
File, ResponseError
|
||||||
|
-
|
||||||
|
+from swift.common.constraints import MAX_FILE_SIZE, MAX_META_NAME_LENGTH, \
|
||||||
|
+ MAX_META_VALUE_LENGTH, MAX_META_COUNT, MAX_META_OVERALL_SIZE, \
|
||||||
|
+ MAX_OBJECT_NAME_LENGTH, CONTAINER_LISTING_LIMIT, ACCOUNT_LISTING_LIMIT, \
|
||||||
|
+ MAX_ACCOUNT_NAME_LENGTH, MAX_CONTAINER_NAME_LENGTH
|
||||||
|
+
|
||||||
|
+default_constraints = dict((
|
||||||
|
+ ('max_file_size', MAX_FILE_SIZE),
|
||||||
|
+ ('max_meta_name_length', MAX_META_NAME_LENGTH),
|
||||||
|
+ ('max_meta_value_length', MAX_META_VALUE_LENGTH),
|
||||||
|
+ ('max_meta_count', MAX_META_COUNT),
|
||||||
|
+ ('max_meta_overall_size', MAX_META_OVERALL_SIZE),
|
||||||
|
+ ('max_object_name_length', MAX_OBJECT_NAME_LENGTH),
|
||||||
|
+ ('container_listing_limit', CONTAINER_LISTING_LIMIT),
|
||||||
|
+ ('account_listing_limit', ACCOUNT_LISTING_LIMIT),
|
||||||
|
+ ('max_account_name_length', MAX_ACCOUNT_NAME_LENGTH),
|
||||||
|
+ ('max_container_name_length', MAX_CONTAINER_NAME_LENGTH)))
|
||||||
|
+constraints_conf = ConfigParser()
|
||||||
|
+conf_exists = constraints_conf.read('/etc/swift/swift.conf')
|
||||||
|
+# Constraints are set first from the test config, then from
|
||||||
|
+# /etc/swift/swift.conf if it exists. If swift.conf doesn't exist,
|
||||||
|
+# then limit test coverage. This allows SAIO tests to work fine but
|
||||||
|
+# requires remote funtional testing to know something about the cluster
|
||||||
|
+# that is being tested.
|
||||||
|
config = get_config()
|
||||||
|
+for k in default_constraints:
|
||||||
|
+ if k in config:
|
||||||
|
+ # prefer what's in test.conf
|
||||||
|
+ config[k] = int(config[k])
|
||||||
|
+ elif conf_exists:
|
||||||
|
+ # swift.conf exists, so use what's defined there (or swift defaults)
|
||||||
|
+ # This normally happens when the test is running locally to the cluster
|
||||||
|
+ # as in a SAIO.
|
||||||
|
+ config[k] = default_constraints[k]
|
||||||
|
+ else:
|
||||||
|
+ # .functests don't know what the constraints of the tested cluster are,
|
||||||
|
+ # so the tests can't reliably pass or fail. Therefore, skip those
|
||||||
|
+ # tests.
|
||||||
|
+ config[k] = '%s constraint is not defined' % k
|
||||||
|
+
|
||||||
|
+def load_constraint(name):
|
||||||
|
+ c = config[name]
|
||||||
|
+ if not isinstance(c, int):
|
||||||
|
+ raise SkipTest(c)
|
||||||
|
+ return c
|
||||||
|
|
||||||
|
locale.setlocale(locale.LC_COLLATE, config.get('collate', 'C'))
|
||||||
|
|
||||||
|
@@ -233,7 +276,7 @@ class TestAccount(Base):
|
||||||
|
'application/xml; charset=utf-8')
|
||||||
|
|
||||||
|
def testListingLimit(self):
|
||||||
|
- limit = 10000
|
||||||
|
+ limit = load_constraint('account_listing_limit')
|
||||||
|
|
||||||
|
for l in (1, 100, limit/2, limit-1, limit, limit+1, limit*2):
|
||||||
|
p = {'limit':l}
|
||||||
|
@@ -361,7 +404,7 @@ class TestContainer(Base):
|
||||||
|
set_up = False
|
||||||
|
|
||||||
|
def testContainerNameLimit(self):
|
||||||
|
- limit = 256
|
||||||
|
+ limit = load_constraint('max_container_name_length')
|
||||||
|
|
||||||
|
for l in (limit-100, limit-10, limit-1, limit,
|
||||||
|
limit+1, limit+10, limit+100):
|
||||||
|
@@ -406,6 +449,7 @@ class TestContainer(Base):
|
||||||
|
self.assert_(cont.files(parms={'prefix': f}) == [f])
|
||||||
|
|
||||||
|
def testPrefixAndLimit(self):
|
||||||
|
+ load_constraint('container_listing_limit')
|
||||||
|
cont = self.env.account.container(Utils.create_name())
|
||||||
|
self.assert_(cont.create())
|
||||||
|
|
||||||
|
@@ -949,7 +993,7 @@ class TestFile(Base):
|
||||||
|
self.assert_status(404)
|
||||||
|
|
||||||
|
def testNameLimit(self):
|
||||||
|
- limit = 1024
|
||||||
|
+ limit = load_constraint('max_object_name_length')
|
||||||
|
|
||||||
|
for l in (1, 10, limit/2, limit-1, limit, limit+1, limit*2):
|
||||||
|
file = self.env.container.file('a'*l)
|
||||||
|
@@ -997,13 +1041,12 @@ class TestFile(Base):
|
||||||
|
self.assert_status(400)
|
||||||
|
|
||||||
|
def testMetadataNumberLimit(self):
|
||||||
|
- number_limit = 90
|
||||||
|
+ number_limit = load_constraint('max_meta_count')
|
||||||
|
+ size_limit = load_constraint('max_meta_overall_size')
|
||||||
|
|
||||||
|
for i in (number_limit-10, number_limit-1, number_limit,
|
||||||
|
number_limit+1, number_limit+10, number_limit+100):
|
||||||
|
|
||||||
|
- size_limit = 4096
|
||||||
|
-
|
||||||
|
j = size_limit/(i * 2)
|
||||||
|
|
||||||
|
size = 0
|
||||||
|
@@ -1093,7 +1136,7 @@ class TestFile(Base):
|
||||||
|
self.assert_(file.read(hdrs={'Range': r}) == data[0:1000])
|
||||||
|
|
||||||
|
def testFileSizeLimit(self):
|
||||||
|
- limit = 5*2**30 + 2
|
||||||
|
+ limit = load_constraint('max_file_size')
|
||||||
|
tsecs = 3
|
||||||
|
|
||||||
|
for i in (limit-100, limit-10, limit-1, limit, limit+1, limit+10,
|
||||||
|
@@ -1147,7 +1190,8 @@ class TestFile(Base):
|
||||||
|
self.assert_status(200)
|
||||||
|
|
||||||
|
def testMetadataLengthLimits(self):
|
||||||
|
- key_limit, value_limit = 128, 256
|
||||||
|
+ key_limit = load_constraint('max_meta_name_length')
|
||||||
|
+ value_limit = load_constraint('max_meta_value_length')
|
||||||
|
lengths = [[key_limit, value_limit], [key_limit, value_limit+1], \
|
||||||
|
[key_limit+1, value_limit], [key_limit, 0], \
|
||||||
|
[key_limit, value_limit*10], [key_limit*10, value_limit]]
|
||||||
|
diff --git a/test/unit/common/test_constraints.py b/test/unit/common/test_constraints.py
|
||||||
|
index 478b2a8..4b0c997 100644
|
||||||
|
--- a/test/unit/common/test_constraints.py
|
||||||
|
+++ b/test/unit/common/test_constraints.py
|
||||||
|
@@ -84,8 +84,13 @@ class TestConstraints(unittest.TestCase):
|
||||||
|
x += 1
|
||||||
|
self.assertEquals(constraints.check_metadata(Request.blank('/',
|
||||||
|
headers=headers), 'object'), None)
|
||||||
|
- headers['X-Object-Meta-9999%s' %
|
||||||
|
- ('a' * (constraints.MAX_META_NAME_LENGTH - 4))] = \
|
||||||
|
+ # add two more headers in case adding just one falls exactly on the
|
||||||
|
+ # limit (eg one header adds 1024 and the limit is 2048)
|
||||||
|
+ headers['X-Object-Meta-%04d%s' %
|
||||||
|
+ (x, 'a' * (constraints.MAX_META_NAME_LENGTH - 4))] = \
|
||||||
|
+ 'v' * constraints.MAX_META_VALUE_LENGTH
|
||||||
|
+ headers['X-Object-Meta-%04d%s' %
|
||||||
|
+ (x + 1, 'a' * (constraints.MAX_META_NAME_LENGTH - 4))] = \
|
||||||
|
'v' * constraints.MAX_META_VALUE_LENGTH
|
||||||
|
self.assert_(isinstance(constraints.check_metadata(Request.blank('/',
|
||||||
|
headers=headers), 'object'), HTTPBadRequest))
|
||||||
|
diff --git a/test/unit/obj/test_server.py b/test/unit/obj/test_server.py
|
||||||
|
index 075700e..5160830 100644
|
||||||
|
--- a/test/unit/obj/test_server.py
|
||||||
|
+++ b/test/unit/obj/test_server.py
|
||||||
|
@@ -38,6 +38,7 @@ from swift.common import utils
|
||||||
|
from swift.common.utils import hash_path, mkdirs, normalize_timestamp, \
|
||||||
|
NullLogger, storage_directory
|
||||||
|
from swift.common.exceptions import DiskFileNotExist
|
||||||
|
+from swift.common import constraints
|
||||||
|
from swift.obj import replicator
|
||||||
|
from eventlet import tpool
|
||||||
|
|
||||||
|
@@ -1355,7 +1356,9 @@ class TestObjectController(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_max_object_name_length(self):
|
||||||
|
timestamp = normalize_timestamp(time())
|
||||||
|
- req = Request.blank('/sda1/p/a/c/' + ('1' * 1024),
|
||||||
|
+ max_name_len = constraints.MAX_OBJECT_NAME_LENGTH
|
||||||
|
+ req = Request.blank('/sda1/p/a/c/' + ('1' * max_name_len),
|
||||||
|
+
|
||||||
|
environ={'REQUEST_METHOD': 'PUT'},
|
||||||
|
headers={'X-Timestamp': timestamp,
|
||||||
|
'Content-Length': '4',
|
||||||
|
@@ -1363,7 +1366,7 @@ class TestObjectController(unittest.TestCase):
|
||||||
|
req.body = 'DATA'
|
||||||
|
resp = self.object_controller.PUT(req)
|
||||||
|
self.assertEquals(resp.status_int, 201)
|
||||||
|
- req = Request.blank('/sda1/p/a/c/' + ('2' * 1025),
|
||||||
|
+ req = Request.blank('/sda1/p/a/c/' + ('2' * (max_name_len + 1)),
|
||||||
|
environ={'REQUEST_METHOD': 'PUT'},
|
||||||
|
headers={'X-Timestamp': timestamp,
|
||||||
|
'Content-Length': '4',
|
||||||
|
diff --git a/test/unit/proxy/test_server.py b/test/unit/proxy/test_server.py
|
||||||
|
index 364370e..d28f604 100644
|
||||||
|
--- a/test/unit/proxy/test_server.py
|
||||||
|
+++ b/test/unit/proxy/test_server.py
|
||||||
|
@@ -45,7 +45,8 @@ from swift.container import server as container_server
|
||||||
|
from swift.obj import server as object_server
|
||||||
|
from swift.common import ring
|
||||||
|
from swift.common.constraints import MAX_META_NAME_LENGTH, \
|
||||||
|
- MAX_META_VALUE_LENGTH, MAX_META_COUNT, MAX_META_OVERALL_SIZE, MAX_FILE_SIZE
|
||||||
|
+ MAX_META_VALUE_LENGTH, MAX_META_COUNT, MAX_META_OVERALL_SIZE, \
|
||||||
|
+ MAX_FILE_SIZE, MAX_ACCOUNT_NAME_LENGTH, MAX_CONTAINER_NAME_LENGTH
|
||||||
|
from swift.common.utils import mkdirs, normalize_timestamp, NullLogger
|
||||||
|
from swift.common.wsgi import monkey_patch_mimetools
|
||||||
|
|
||||||
|
@@ -1168,6 +1169,7 @@ class TestObjectController(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_POST_meta_val_len(self):
|
||||||
|
with save_globals():
|
||||||
|
+ limit = MAX_META_VALUE_LENGTH
|
||||||
|
self.app.object_post_as_copy = False
|
||||||
|
controller = proxy_server.ObjectController(self.app, 'account',
|
||||||
|
'container', 'object')
|
||||||
|
@@ -1175,42 +1177,44 @@ class TestObjectController(unittest.TestCase):
|
||||||
|
fake_http_connect(200, 200, 202, 202, 202)
|
||||||
|
# acct cont obj obj obj
|
||||||
|
req = Request.blank('/a/c/o', {}, headers={
|
||||||
|
- 'Content-Type': 'foo/bar',
|
||||||
|
- 'X-Object-Meta-Foo': 'x' * 256})
|
||||||
|
+ 'Content-Type': 'foo/bar',
|
||||||
|
+ 'X-Object-Meta-Foo': 'x' * limit})
|
||||||
|
self.app.update_request(req)
|
||||||
|
res = controller.POST(req)
|
||||||
|
self.assertEquals(res.status_int, 202)
|
||||||
|
proxy_server.http_connect = fake_http_connect(202, 202, 202)
|
||||||
|
req = Request.blank('/a/c/o', {}, headers={
|
||||||
|
- 'Content-Type': 'foo/bar',
|
||||||
|
- 'X-Object-Meta-Foo': 'x' * 257})
|
||||||
|
+ 'Content-Type': 'foo/bar',
|
||||||
|
+ 'X-Object-Meta-Foo': 'x' * (limit + 1)})
|
||||||
|
self.app.update_request(req)
|
||||||
|
res = controller.POST(req)
|
||||||
|
self.assertEquals(res.status_int, 400)
|
||||||
|
|
||||||
|
def test_POST_as_copy_meta_val_len(self):
|
||||||
|
with save_globals():
|
||||||
|
+ limit = MAX_META_VALUE_LENGTH
|
||||||
|
controller = proxy_server.ObjectController(self.app, 'account',
|
||||||
|
'container', 'object')
|
||||||
|
proxy_server.http_connect = \
|
||||||
|
fake_http_connect(200, 200, 200, 200, 200, 202, 202, 202)
|
||||||
|
# acct cont objc objc objc obj obj obj
|
||||||
|
req = Request.blank('/a/c/o', {}, headers={
|
||||||
|
- 'Content-Type': 'foo/bar',
|
||||||
|
- 'X-Object-Meta-Foo': 'x' * 256})
|
||||||
|
+ 'Content-Type': 'foo/bar',
|
||||||
|
+ 'X-Object-Meta-Foo': 'x' * limit})
|
||||||
|
self.app.update_request(req)
|
||||||
|
res = controller.POST(req)
|
||||||
|
self.assertEquals(res.status_int, 202)
|
||||||
|
proxy_server.http_connect = fake_http_connect(202, 202, 202)
|
||||||
|
req = Request.blank('/a/c/o', {}, headers={
|
||||||
|
- 'Content-Type': 'foo/bar',
|
||||||
|
- 'X-Object-Meta-Foo': 'x' * 257})
|
||||||
|
+ 'Content-Type': 'foo/bar',
|
||||||
|
+ 'X-Object-Meta-Foo': 'x' * (limit + 1)})
|
||||||
|
self.app.update_request(req)
|
||||||
|
res = controller.POST(req)
|
||||||
|
self.assertEquals(res.status_int, 400)
|
||||||
|
|
||||||
|
def test_POST_meta_key_len(self):
|
||||||
|
with save_globals():
|
||||||
|
+ limit = MAX_META_NAME_LENGTH
|
||||||
|
self.app.object_post_as_copy = False
|
||||||
|
controller = proxy_server.ObjectController(self.app, 'account',
|
||||||
|
'container', 'object')
|
||||||
|
@@ -1219,20 +1223,21 @@ class TestObjectController(unittest.TestCase):
|
||||||
|
# acct cont obj obj obj
|
||||||
|
req = Request.blank('/a/c/o', {}, headers={
|
||||||
|
'Content-Type': 'foo/bar',
|
||||||
|
- ('X-Object-Meta-' + 'x' * 128): 'x'})
|
||||||
|
+ ('X-Object-Meta-' + 'x' * limit): 'x'})
|
||||||
|
self.app.update_request(req)
|
||||||
|
res = controller.POST(req)
|
||||||
|
self.assertEquals(res.status_int, 202)
|
||||||
|
proxy_server.http_connect = fake_http_connect(202, 202, 202)
|
||||||
|
req = Request.blank('/a/c/o', {}, headers={
|
||||||
|
'Content-Type': 'foo/bar',
|
||||||
|
- ('X-Object-Meta-' + 'x' * 129): 'x'})
|
||||||
|
+ ('X-Object-Meta-' + 'x' * (limit + 1)): 'x'})
|
||||||
|
self.app.update_request(req)
|
||||||
|
res = controller.POST(req)
|
||||||
|
self.assertEquals(res.status_int, 400)
|
||||||
|
|
||||||
|
def test_POST_as_copy_meta_key_len(self):
|
||||||
|
with save_globals():
|
||||||
|
+ limit = MAX_META_NAME_LENGTH
|
||||||
|
controller = proxy_server.ObjectController(self.app, 'account',
|
||||||
|
'container', 'object')
|
||||||
|
proxy_server.http_connect = \
|
||||||
|
@@ -1240,24 +1245,25 @@ class TestObjectController(unittest.TestCase):
|
||||||
|
# acct cont objc objc objc obj obj obj
|
||||||
|
req = Request.blank('/a/c/o', {}, headers={
|
||||||
|
'Content-Type': 'foo/bar',
|
||||||
|
- ('X-Object-Meta-' + 'x' * 128): 'x'})
|
||||||
|
+ ('X-Object-Meta-' + 'x' * limit): 'x'})
|
||||||
|
self.app.update_request(req)
|
||||||
|
res = controller.POST(req)
|
||||||
|
self.assertEquals(res.status_int, 202)
|
||||||
|
proxy_server.http_connect = fake_http_connect(202, 202, 202)
|
||||||
|
req = Request.blank('/a/c/o', {}, headers={
|
||||||
|
'Content-Type': 'foo/bar',
|
||||||
|
- ('X-Object-Meta-' + 'x' * 129): 'x'})
|
||||||
|
+ ('X-Object-Meta-' + 'x' * (limit + 1)): 'x'})
|
||||||
|
self.app.update_request(req)
|
||||||
|
res = controller.POST(req)
|
||||||
|
self.assertEquals(res.status_int, 400)
|
||||||
|
|
||||||
|
def test_POST_meta_count(self):
|
||||||
|
with save_globals():
|
||||||
|
+ limit = MAX_META_COUNT
|
||||||
|
controller = proxy_server.ObjectController(self.app, 'account',
|
||||||
|
'container', 'object')
|
||||||
|
headers = dict(
|
||||||
|
- (('X-Object-Meta-' + str(i), 'a') for i in xrange(91)))
|
||||||
|
+ (('X-Object-Meta-' + str(i), 'a') for i in xrange(limit + 1)))
|
||||||
|
headers.update({'Content-Type': 'foo/bar'})
|
||||||
|
proxy_server.http_connect = fake_http_connect(202, 202, 202)
|
||||||
|
req = Request.blank('/a/c/o', {}, headers=headers)
|
||||||
|
@@ -1267,10 +1273,13 @@ class TestObjectController(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_POST_meta_size(self):
|
||||||
|
with save_globals():
|
||||||
|
+ limit = MAX_META_OVERALL_SIZE
|
||||||
|
controller = proxy_server.ObjectController(self.app, 'account',
|
||||||
|
'container', 'object')
|
||||||
|
+ count = limit / 256 # enough to cause the limit to be reched
|
||||||
|
headers = dict(
|
||||||
|
- (('X-Object-Meta-' + str(i), 'a' * 256) for i in xrange(1000)))
|
||||||
|
+ (('X-Object-Meta-' + str(i), 'a' * 256)
|
||||||
|
+ for i in xrange(count + 1)))
|
||||||
|
headers.update({'Content-Type': 'foo/bar'})
|
||||||
|
proxy_server.http_connect = fake_http_connect(202, 202, 202)
|
||||||
|
req = Request.blank('/a/c/o', {}, headers=headers)
|
||||||
|
@@ -3206,13 +3215,14 @@ class TestContainerController(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_PUT_max_container_name_length(self):
|
||||||
|
with save_globals():
|
||||||
|
+ limit = MAX_CONTAINER_NAME_LENGTH
|
||||||
|
controller = proxy_server.ContainerController(self.app, 'account',
|
||||||
|
- '1' * 256)
|
||||||
|
+ '1' * limit)
|
||||||
|
self.assert_status_map(controller.PUT,
|
||||||
|
(200, 200, 200, 201, 201, 201), 201,
|
||||||
|
missing_container=True)
|
||||||
|
controller = proxy_server.ContainerController(self.app, 'account',
|
||||||
|
- '2' * 257)
|
||||||
|
+ '2' * (limit + 1))
|
||||||
|
self.assert_status_map(controller.PUT, (201, 201, 201), 400,
|
||||||
|
missing_container=True)
|
||||||
|
|
||||||
|
@@ -3813,9 +3823,11 @@ class TestAccountController(unittest.TestCase):
|
||||||
|
def test_PUT_max_account_name_length(self):
|
||||||
|
with save_globals():
|
||||||
|
self.app.allow_account_management = True
|
||||||
|
- controller = proxy_server.AccountController(self.app, '1' * 256)
|
||||||
|
+ limit = MAX_ACCOUNT_NAME_LENGTH
|
||||||
|
+ controller = proxy_server.AccountController(self.app, '1' * limit)
|
||||||
|
self.assert_status_map(controller.PUT, (201, 201, 201), 201)
|
||||||
|
- controller = proxy_server.AccountController(self.app, '2' * 257)
|
||||||
|
+ controller = proxy_server.AccountController(
|
||||||
|
+ self.app, '2' * (limit + 1))
|
||||||
|
self.assert_status_map(controller.PUT, (201, 201, 201), 400)
|
||||||
|
|
||||||
|
def test_PUT_connect_exceptions(self):
|
||||||
|
--
|
||||||
|
1.7.7.6
|
||||||
|
|
@ -23,7 +23,8 @@
|
|||||||
|
|
||||||
%if ( 0%{?fedora} ) || ( 0%{?rhel} && 0%{?rhel} >= 6 )
|
%if ( 0%{?fedora} ) || ( 0%{?rhel} && 0%{?rhel} >= 6 )
|
||||||
%global SWIFTVER 1.4.8
|
%global SWIFTVER 1.4.8
|
||||||
%global _with_swift true
|
%global UFOVER 1.1
|
||||||
|
%global _with_ufo true
|
||||||
%endif
|
%endif
|
||||||
%if ( 0%{?fedora} && 0%{?fedora} > 16 ) || ( 0%{?rhel} && 0%{?rhel} > 6 )
|
%if ( 0%{?fedora} && 0%{?fedora} > 16 ) || ( 0%{?rhel} && 0%{?rhel} > 6 )
|
||||||
%global _with_systemd true
|
%global _with_systemd true
|
||||||
@ -32,7 +33,7 @@
|
|||||||
Summary: Cluster File System
|
Summary: Cluster File System
|
||||||
Name: glusterfs
|
Name: glusterfs
|
||||||
Version: 3.3.1
|
Version: 3.3.1
|
||||||
Release: 3%{?dist}
|
Release: 4%{?dist}
|
||||||
License: GPLv3+ and (GPLv2 or LGPLv3+)
|
License: GPLv3+ and (GPLv2 or LGPLv3+)
|
||||||
Group: System Environment/Base
|
Group: System Environment/Base
|
||||||
Vendor: Red Hat
|
Vendor: Red Hat
|
||||||
@ -221,7 +222,7 @@ is in user space and easily manageable.
|
|||||||
|
|
||||||
This package provides the development libraries.
|
This package provides the development libraries.
|
||||||
|
|
||||||
%if 0%{?_with_swift:1}
|
%if 0%{?_with_ufo:1}
|
||||||
%package swift
|
%package swift
|
||||||
|
|
||||||
Summary: GlusterFS OpenStack Object Storage
|
Summary: GlusterFS OpenStack Object Storage
|
||||||
@ -253,7 +254,7 @@ Patch12: openstack-swift-newdeps.patch
|
|||||||
Patch13: openstack-swift-docmod.patch
|
Patch13: openstack-swift-docmod.patch
|
||||||
Patch14: openstack-swift-nonet.patch
|
Patch14: openstack-swift-nonet.patch
|
||||||
%endif
|
%endif
|
||||||
Patch15: glusterfs-3.3.0.swift.patch
|
Patch15: glusterfs-3.3.1.swift.constraints.backport.patch
|
||||||
#BuildRoot: %(mktemp -ud %{_tmppath}/swift-%{SWIFTVER}-%{release}-XXXXXX)
|
#BuildRoot: %(mktemp -ud %{_tmppath}/swift-%{SWIFTVER}-%{release}-XXXXXX)
|
||||||
|
|
||||||
BuildRequires: dos2unix
|
BuildRequires: dos2unix
|
||||||
@ -374,7 +375,7 @@ in clusters for reliable, redundant, and large-scale storage of static objects.
|
|||||||
|
|
||||||
This package contains documentation files for %{name}-swift.
|
This package contains documentation files for %{name}-swift.
|
||||||
|
|
||||||
%package swift-plugin
|
%package swift-ufo
|
||||||
Summary: GlusterFS Unified File and Object Storage.
|
Summary: GlusterFS Unified File and Object Storage.
|
||||||
Group: Applications/System
|
Group: Applications/System
|
||||||
License: ASL 2.0
|
License: ASL 2.0
|
||||||
@ -383,9 +384,9 @@ Requires: %{name}-swift = %{version}-%{release}
|
|||||||
Requires: memcached
|
Requires: memcached
|
||||||
Requires: openssl
|
Requires: openssl
|
||||||
Requires: python
|
Requires: python
|
||||||
Source20: gluster-swift-plugins.tar.gz
|
Source20: http://download.gluster.org/pub/gluster/glusterfs/3.3/3.3.1/UFO/gluster-swift-ufo-%{UFOVER}.tar.gz
|
||||||
|
|
||||||
%description swift-plugin
|
%description swift-ufo
|
||||||
Gluster Unified File and Object Storage unifies NAS and object storage
|
Gluster Unified File and Object Storage unifies NAS and object storage
|
||||||
technology. This provides a system for data storage that enables users to access
|
technology. This provides a system for data storage that enables users to access
|
||||||
the same data as an object and as a file, simplifying management and controlling
|
the same data as an object and as a file, simplifying management and controlling
|
||||||
@ -395,8 +396,10 @@ storage costs.
|
|||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q -n %{name}-%{version}
|
%setup -q -n %{name}-%{version}
|
||||||
%if 0%{?_with_swift:1}
|
%if 0%{?_with_ufo:1}
|
||||||
|
# swift-1.4.8
|
||||||
%setup -q -T -D -n %{name}-%{version} -a 10
|
%setup -q -T -D -n %{name}-%{version} -a 10
|
||||||
|
# gluster ufo
|
||||||
%setup -q -T -D -n %{name}-%{version} -a 20
|
%setup -q -T -D -n %{name}-%{version} -a 20
|
||||||
#%patch0 -p0
|
#%patch0 -p0
|
||||||
%patch1 -p0
|
%patch1 -p0
|
||||||
@ -422,7 +425,7 @@ sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool
|
|||||||
|
|
||||||
%{__make} %{?_smp_mflags}
|
%{__make} %{?_smp_mflags}
|
||||||
|
|
||||||
%if 0%{?_with_swift:1}
|
%if 0%{?_with_ufo:1}
|
||||||
cd swift-%{SWIFTVER}
|
cd swift-%{SWIFTVER}
|
||||||
%{__python} setup.py build
|
%{__python} setup.py build
|
||||||
%{__mkdir_p} doc/build
|
%{__mkdir_p} doc/build
|
||||||
@ -430,6 +433,9 @@ cd swift-%{SWIFTVER}
|
|||||||
%{__python} setup.py build_sphinx
|
%{__python} setup.py build_sphinx
|
||||||
%endif
|
%endif
|
||||||
cd ..
|
cd ..
|
||||||
|
cd ufo
|
||||||
|
%{__python} setup.py build
|
||||||
|
cd ..
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%install
|
%install
|
||||||
@ -529,7 +535,7 @@ touch %{buildroot}%{_sharedstatedir}/glusterd/glusterd.info
|
|||||||
%{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/nfs
|
%{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/nfs
|
||||||
%{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/peers
|
%{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/peers
|
||||||
|
|
||||||
%if 0%{?_with_swift:1}
|
%if 0%{?_with_ufo:1}
|
||||||
cd swift-%{SWIFTVER}
|
cd swift-%{SWIFTVER}
|
||||||
%{__python} setup.py install -O1 --skip-build --root %{buildroot}
|
%{__python} setup.py install -O1 --skip-build --root %{buildroot}
|
||||||
%if 0%{?_with_systemd:1}
|
%if 0%{?_with_systemd:1}
|
||||||
@ -553,8 +559,6 @@ install -p -m 0644 %{SOURCE19} %{buildroot}%{_sysconfdir}/tmpfiles.d/gluster-swi
|
|||||||
# Init helper functions
|
# Init helper functions
|
||||||
%{__install} -p -D -m 644 %{SOURCE18} %{buildroot}%{_datarootdir}/gluster-swift/functions
|
%{__install} -p -D -m 644 %{SOURCE18} %{buildroot}%{_datarootdir}/gluster-swift/functions
|
||||||
%endif
|
%endif
|
||||||
# Remove tests
|
|
||||||
%{__rm} -rf %{buildroot}/%{python_sitelib}/test
|
|
||||||
# Misc other
|
# Misc other
|
||||||
%{__install} -d -m 755 %{buildroot}%{_sysconfdir}/swift
|
%{__install} -d -m 755 %{buildroot}%{_sysconfdir}/swift
|
||||||
%{__install} -d -m 755 %{buildroot}%{_sysconfdir}/swift/account-server
|
%{__install} -d -m 755 %{buildroot}%{_sysconfdir}/swift/account-server
|
||||||
@ -568,21 +572,16 @@ install -p -m 0644 %{SOURCE19} %{buildroot}%{_sysconfdir}/tmpfiles.d/gluster-swi
|
|||||||
%{__install} -d -m 755 %{buildroot}%{_localstatedir}/run/swift/object-server
|
%{__install} -d -m 755 %{buildroot}%{_localstatedir}/run/swift/object-server
|
||||||
%{__install} -d -m 755 %{buildroot}%{_localstatedir}/run/swift/proxy-server
|
%{__install} -d -m 755 %{buildroot}%{_localstatedir}/run/swift/proxy-server
|
||||||
cd ..
|
cd ..
|
||||||
|
cd ufo
|
||||||
%{__mkdir_p} %{buildroot}%{python_sitelib}/swift/plugins
|
%{__python} setup.py install -O1 --skip-build --root %{buildroot}
|
||||||
#%{__mkdir_p} %{buildroot}%{_sysconfdir}/swift
|
|
||||||
cd plugins
|
|
||||||
%{__install} -p -D -m 755 constraints.py %{buildroot}%{python_sitelib}/swift/plugins
|
|
||||||
%{__install} -p -D -m 755 DiskDir.py %{buildroot}%{python_sitelib}/swift/plugins
|
|
||||||
%{__install} -p -D -m 755 DiskFile.py %{buildroot}%{python_sitelib}/swift/plugins
|
|
||||||
%{__install} -p -D -m 755 Glusterfs.py %{buildroot}%{python_sitelib}/swift/plugins
|
|
||||||
%{__install} -p -D -m 755 __init__.py %{buildroot}%{python_sitelib}/swift/plugins
|
|
||||||
%{__install} -p -D -m 755 utils.py %{buildroot}%{python_sitelib}/swift/plugins
|
|
||||||
cp -r conf/* %{buildroot}%{_sysconfdir}/swift
|
|
||||||
cd ..
|
cd ..
|
||||||
|
%{__mkdir_p} %{buildroot}%{_sysconfdir}/swift
|
||||||
|
cp -r ufo/etc/* %{buildroot}%{_sysconfdir}/swift/
|
||||||
|
%{__mkdir_p} %{buildroot}%{_bindir}
|
||||||
|
cp ufo/bin/gluster-swift-gen-builders %{buildroot}%{_bindir}/
|
||||||
%endif
|
%endif
|
||||||
|
# Remove tests
|
||||||
|
%{__rm} -rf %{buildroot}/%{python_sitelib}/test
|
||||||
%clean
|
%clean
|
||||||
%{__rm} -rf %{buildroot}
|
%{__rm} -rf %{buildroot}
|
||||||
|
|
||||||
@ -707,7 +706,7 @@ fi
|
|||||||
%exclude %{_includedir}/glusterfs/y.tab.h
|
%exclude %{_includedir}/glusterfs/y.tab.h
|
||||||
%{_libdir}/*.so
|
%{_libdir}/*.so
|
||||||
|
|
||||||
%if 0%{?_with_swift:1}
|
%if 0%{?_with_ufo:1}
|
||||||
%files swift
|
%files swift
|
||||||
%defattr(-,root,root,-)
|
%defattr(-,root,root,-)
|
||||||
%doc swift-%{SWIFTVER}/AUTHORS
|
%doc swift-%{SWIFTVER}/AUTHORS
|
||||||
@ -805,9 +804,11 @@ fi
|
|||||||
%defattr(-,root,root,-)
|
%defattr(-,root,root,-)
|
||||||
%doc swift-%{SWIFTVER}/LICENSE
|
%doc swift-%{SWIFTVER}/LICENSE
|
||||||
|
|
||||||
%files swift-plugin
|
%files swift-ufo
|
||||||
%defattr(-,root,root,-)
|
%defattr(-,root,root,-)
|
||||||
%{python_sitelib}/swift/plugins
|
%{python_sitelib}/gluster
|
||||||
|
%{python_sitelib}/gluster_swift_ufo-%{UFOVER}-*.egg-info
|
||||||
|
%{_bindir}/gluster-swift-gen-builders
|
||||||
%{_sysconfdir}/swift
|
%{_sysconfdir}/swift
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
@ -876,7 +877,7 @@ if [ $1 -ge 1 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
%if 0%{?_with_swift:1}
|
%if 0%{?_with_ufo:1}
|
||||||
%pre swift
|
%pre swift
|
||||||
getent group swift >/dev/null || groupadd -r swift -g 160
|
getent group swift >/dev/null || groupadd -r swift -g 160
|
||||||
getent passwd swift >/dev/null || \
|
getent passwd swift >/dev/null || \
|
||||||
@ -986,6 +987,12 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri Dec 7 2012 Kaleb S. KEITHLEY <kkeithle[at]redhat.com> - 3.3.1-4
|
||||||
|
- Swift+UFO, now with less swift forkage. Specifically the only patches
|
||||||
|
to swift are those already used for the Fedora openstack-swift packages
|
||||||
|
_plus_ our backport of the upstream constraints config changes that have
|
||||||
|
been accepted into grizzly.
|
||||||
|
|
||||||
* Mon Nov 16 2012 Kaleb S. KEITHLEY <kkeithle[at]redhat.com> - 3.3.1-3
|
* Mon Nov 16 2012 Kaleb S. KEITHLEY <kkeithle[at]redhat.com> - 3.3.1-3
|
||||||
- add Requires: rpcbind for minimum install systems where rpcbind isn't
|
- add Requires: rpcbind for minimum install systems where rpcbind isn't
|
||||||
installed; usually this is a no-op.
|
installed; usually this is a no-op.
|
||||||
|
1
sources
1
sources
@ -1,2 +1,3 @@
|
|||||||
4c9f291de887b1193d5d1acac4003360 glusterfs-3.3.1.tar.gz
|
4c9f291de887b1193d5d1acac4003360 glusterfs-3.3.1.tar.gz
|
||||||
785ae9ba4e1f6fc256cd6a697bb2861f swift-1.4.8.tar.gz
|
785ae9ba4e1f6fc256cd6a697bb2861f swift-1.4.8.tar.gz
|
||||||
|
c1041b0551be722363f18f3a5664d0cf gluster-swift-ufo-1.1.tar.gz
|
||||||
|
Loading…
Reference in New Issue
Block a user