From 6a8e9a70e9489a8f17405adf64462899d6a4ca81 Mon Sep 17 00:00:00 2001 From: Luis Pabon Date: Fri, 10 Jan 2014 19:44:39 -0500 Subject: Sync with OpenStack v1.11.0 Jan 10 2014 Updated tox.ini, functional tests, and proxy unit tests. BUG: https://bugs.launchpad.net/bugs/1268017 Change-Id: I5ff8359b8abdb8fe5ae82492c12f57c395992735 Signed-off-by: Luis Pabon Reviewed-on: http://review.gluster.org/6682 Reviewed-by: Thiago da Silva Tested-by: Thiago da Silva --- gluster/swift/__init__.py | 2 +- modules/swift | 2 +- test/functional/swift_test_client.py | 23 +- test/functional/tests.py | 79 ++-- test/unit/__init__.py | 6 +- test/unit/proxy/controllers/test_account.py | 102 ++++- test/unit/proxy/controllers/test_base.py | 113 +++++- test/unit/proxy/controllers/test_container.py | 62 ++- test/unit/proxy/controllers/test_info.py | 293 ++++++++++++++ test/unit/proxy/test_server.py | 561 ++++++++++++++++---------- tools/requirements.txt | 8 + tools/test-requires | 2 +- tox.ini | 7 +- 13 files changed, 995 insertions(+), 265 deletions(-) create mode 100644 test/unit/proxy/controllers/test_info.py create mode 100644 tools/requirements.txt diff --git a/gluster/swift/__init__.py b/gluster/swift/__init__.py index fbd38e6..9bfdc31 100644 --- a/gluster/swift/__init__.py +++ b/gluster/swift/__init__.py @@ -45,6 +45,6 @@ class PkgInfo(object): ### ### Change the Package version here ### -_pkginfo = PkgInfo('1.10.2', '0', 'gluster_swift', False) +_pkginfo = PkgInfo('1.11.0', '0', 'gluster_swift', False) __version__ = _pkginfo.pretty_version __canonical_version__ = _pkginfo.canonical_version diff --git a/modules/swift b/modules/swift index 4bfe674..f310006 160000 --- a/modules/swift +++ b/modules/swift @@ -1 +1 @@ -Subproject commit 4bfe6748fd8e746460f5428f3dd161c82b1443a2 +Subproject commit f310006fae1af991097eee5929a1c73051eb1e00 diff --git a/test/functional/swift_test_client.py b/test/functional/swift_test_client.py index d407a33..47e023e 100644 --- a/test/functional/swift_test_client.py +++ b/test/functional/swift_test_client.py @@ -65,7 +65,7 @@ class ResponseError(Exception): def listing_empty(method): - for i in xrange(0, 6): + for i in xrange(6): if len(method()) == 0: return True @@ -208,7 +208,11 @@ class Connection(object): def make_request(self, method, path=[], data='', hdrs={}, parms={}, cfg={}): - path = self.make_path(path, cfg=cfg) + if not cfg.get('verbatim_path'): + # Set verbatim_path=True to make a request to exactly the given + # path, not storage path + given path. Useful for + # non-account/container/object requests. + path = self.make_path(path, cfg=cfg) headers = self.make_headers(hdrs, cfg=cfg) if isinstance(parms, dict) and parms: quote = urllib.quote @@ -719,7 +723,8 @@ class File(Base): else: raise RuntimeError - def write(self, data='', hdrs={}, parms={}, callback=None, cfg={}): + def write(self, data='', hdrs={}, parms={}, callback=None, cfg={}, + return_resp=False): block_size = 2 ** 20 if isinstance(data, file): @@ -763,6 +768,9 @@ class File(Base): pass self.md5 = self.compute_md5sum(data) + if return_resp: + return self.conn.response + return True def write_random(self, size=None, hdrs={}, parms={}, cfg={}): @@ -772,3 +780,12 @@ class File(Base): self.conn.make_path(self.path)) self.md5 = self.compute_md5sum(StringIO.StringIO(data)) return data + + def write_random_return_resp(self, size=None, hdrs={}, parms={}, cfg={}): + data = self.random_data(size) + resp = self.write(data, hdrs=hdrs, parms=parms, cfg=cfg, + return_resp=True) + if not resp: + raise ResponseError(self.conn.response) + self.md5 = self.compute_md5sum(StringIO.StringIO(data)) + return resp diff --git a/test/functional/tests.py b/test/functional/tests.py index 808208d..e4b778b 100644 --- a/test/functional/tests.py +++ b/test/functional/tests.py @@ -1704,8 +1704,14 @@ class TestFileComparisonEnv: file_item.write_random(cls.file_size) cls.files.append(file_item) - cls.time_old = time.asctime(time.localtime(time.time() - 86400)) - cls.time_new = time.asctime(time.localtime(time.time() + 86400)) + cls.time_old_f1 = time.strftime("%a, %d %b %Y %H:%M:%S GMT", + time.gmtime(time.time() - 86400)) + cls.time_old_f2 = time.strftime("%A, %d-%b-%y %H:%M:%S GMT", + time.gmtime(time.time() - 86400)) + cls.time_old_f3 = time.strftime("%a %b %d %H:%M:%S %Y", + time.gmtime(time.time() - 86400)) + cls.time_new = time.strftime("%a, %d %b %Y %H:%M:%S GMT", + time.gmtime(time.time() + 86400)) class TestFileComparison(Base): @@ -1732,7 +1738,7 @@ class TestFileComparison(Base): def testIfModifiedSince(self): for file_item in self.env.files: - hdrs = {'If-Modified-Since': self.env.time_old} + hdrs = {'If-Modified-Since': self.env.time_old_f1} self.assert_(file_item.read(hdrs=hdrs)) hdrs = {'If-Modified-Since': self.env.time_new} @@ -1744,7 +1750,7 @@ class TestFileComparison(Base): hdrs = {'If-Unmodified-Since': self.env.time_new} self.assert_(file_item.read(hdrs=hdrs)) - hdrs = {'If-Unmodified-Since': self.env.time_old} + hdrs = {'If-Unmodified-Since': self.env.time_old_f2} self.assertRaises(ResponseError, file_item.read, hdrs=hdrs) self.assert_status(412) @@ -1760,10 +1766,32 @@ class TestFileComparison(Base): self.assert_status(412) hdrs = {'If-Match': file_item.md5, - 'If-Unmodified-Since': self.env.time_old} + 'If-Unmodified-Since': self.env.time_old_f3} self.assertRaises(ResponseError, file_item.read, hdrs=hdrs) self.assert_status(412) + def testLastModified(self): + file_name = Utils.create_name() + content_type = Utils.create_name() + + file = self.env.container.file(file_name) + file.content_type = content_type + resp = file.write_random_return_resp(self.env.file_size) + put_last_modified = resp.getheader('last-modified') + + file = self.env.container.file(file_name) + info = file.info() + self.assert_('last_modified' in info) + last_modified = info['last_modified'] + self.assertEqual(put_last_modified, info['last_modified']) + + hdrs = {'If-Modified-Since': last_modified} + self.assertRaises(ResponseError, file.read, hdrs=hdrs) + self.assert_status(304) + + hdrs = {'If-Unmodified-Since': last_modified} + self.assert_(file.read(hdrs=hdrs)) + class TestFileComparisonUTF8(Base2, TestFileComparison): set_up = False @@ -1776,6 +1804,24 @@ class TestSloEnv(object): def setUp(cls): cls.conn = Connection(config) cls.conn.authenticate() + + if cls.slo_enabled is None: + status = cls.conn.make_request('GET', '/info', + cfg={'verbatim_path': True}) + if not (200 <= status <= 299): + # Can't tell if SLO is enabled or not since we're running + # against an old cluster, so let's skip the tests instead of + # possibly having spurious failures. + cls.slo_enabled = False + else: + # Don't bother looking for ValueError here. If something is + # responding to a GET /info request with invalid JSON, then + # the cluster is broken and a test failure will let us know. + cluster_info = json.loads(cls.conn.response.read()) + cls.slo_enabled = 'slo' in cluster_info + if not cls.slo_enabled: + return + cls.account = Account(cls.conn, config.get('account', config['username'])) cls.account.delete_containers() @@ -1785,28 +1831,6 @@ class TestSloEnv(object): if not cls.container.create(): raise ResponseError(cls.conn.response) - # TODO(seriously, anyone can do this): make this use the /info API once - # it lands, both for detection of SLO and for minimum segment size - if cls.slo_enabled is None: - test_file = cls.container.file(".test-slo") - try: - # If SLO is enabled, this'll raise an error since - # X-Static-Large-Object is a reserved header. - # - # If SLO is not enabled, then this will get the usual 2xx - # response. - test_file.write( - "some contents", - hdrs={'X-Static-Large-Object': 'true'}) - except ResponseError as err: - if err.status == 400: - cls.slo_enabled = True - else: - raise - else: - cls.slo_enabled = False - return - seg_info = {} for letter, size in (('a', 1024 * 1024), ('b', 1024 * 1024), @@ -1865,6 +1889,7 @@ class TestSlo(Base): set_up = False def setUp(self): + raise SkipTest("SLO not enabled yet in gluster-swift") super(TestSlo, self).setUp() if self.env.slo_enabled is False: raise SkipTest("SLO not enabled") diff --git a/test/unit/__init__.py b/test/unit/__init__.py index fa46715..847479a 100644 --- a/test/unit/__init__.py +++ b/test/unit/__init__.py @@ -17,9 +17,9 @@ import os import copy -import errno import logging -from sys import exc_info +import errno +import sys from contextlib import contextmanager from collections import defaultdict from tempfile import NamedTemporaryFile @@ -28,7 +28,7 @@ from eventlet.green import socket from tempfile import mkdtemp from shutil import rmtree from test import get_config -from swift.common.utils import config_true_value +from swift.common.utils import config_true_value, LogAdapter from hashlib import md5 from eventlet import sleep, Timeout import logging.handlers diff --git a/test/unit/proxy/controllers/test_account.py b/test/unit/proxy/controllers/test_account.py index 394ada7..eefd57d 100644 --- a/test/unit/proxy/controllers/test_account.py +++ b/test/unit/proxy/controllers/test_account.py @@ -19,7 +19,9 @@ import unittest from swift.common.swob import Request from swift.proxy import server as proxy_server from swift.proxy.controllers.base import headers_to_account_info +from swift.common.constraints import MAX_ACCOUNT_NAME_LENGTH as MAX_ANAME_LEN from test.unit import fake_http_connect, FakeRing, FakeMemcache +from swift.common.request_helpers import get_sys_meta_prefix class TestAccountController(unittest.TestCase): @@ -32,8 +34,8 @@ class TestAccountController(unittest.TestCase): def test_account_info_in_response_env(self): controller = proxy_server.AccountController(self.app, 'AUTH_bob') with mock.patch('swift.proxy.controllers.base.http_connect', - fake_http_connect(200, 200, body='')): - req = Request.blank('/AUTH_bob', {'PATH_INFO': '/AUTH_bob'}) + fake_http_connect(200, body='')): + req = Request.blank('/v1/AUTH_bob', {'PATH_INFO': '/v1/AUTH_bob'}) resp = controller.HEAD(req) self.assertEqual(2, resp.status_int // 100) self.assertTrue('swift.account/AUTH_bob' in resp.environ) @@ -46,22 +48,110 @@ class TestAccountController(unittest.TestCase): 'x-account-meta-temp-url-key-2': 'value'} controller = proxy_server.AccountController(self.app, 'a') - req = Request.blank('/a') + req = Request.blank('/v1/a') with mock.patch('swift.proxy.controllers.base.http_connect', - fake_http_connect(200, 200, headers=owner_headers)): + fake_http_connect(200, headers=owner_headers)): resp = controller.HEAD(req) self.assertEquals(2, resp.status_int // 100) for key in owner_headers: self.assertTrue(key not in resp.headers) - req = Request.blank('/a', environ={'swift_owner': True}) + req = Request.blank('/v1/a', environ={'swift_owner': True}) with mock.patch('swift.proxy.controllers.base.http_connect', - fake_http_connect(200, 200, headers=owner_headers)): + fake_http_connect(200, headers=owner_headers)): resp = controller.HEAD(req) self.assertEquals(2, resp.status_int // 100) for key in owner_headers: self.assertTrue(key in resp.headers) + def test_get_deleted_account(self): + resp_headers = { + 'x-account-status': 'deleted', + } + controller = proxy_server.AccountController(self.app, 'a') + + req = Request.blank('/v1/a') + with mock.patch('swift.proxy.controllers.base.http_connect', + fake_http_connect(404, headers=resp_headers)): + resp = controller.HEAD(req) + self.assertEquals(410, resp.status_int) + + def test_long_acct_names(self): + long_acct_name = '%sLongAccountName' % ('Very' * (MAX_ANAME_LEN // 4)) + controller = proxy_server.AccountController(self.app, long_acct_name) + + req = Request.blank('/v1/%s' % long_acct_name) + with mock.patch('swift.proxy.controllers.base.http_connect', + fake_http_connect(200)): + resp = controller.HEAD(req) + self.assertEquals(400, resp.status_int) + + with mock.patch('swift.proxy.controllers.base.http_connect', + fake_http_connect(200)): + resp = controller.GET(req) + self.assertEquals(400, resp.status_int) + + with mock.patch('swift.proxy.controllers.base.http_connect', + fake_http_connect(200)): + resp = controller.POST(req) + self.assertEquals(400, resp.status_int) + + def _make_callback_func(self, context): + def callback(ipaddr, port, device, partition, method, path, + headers=None, query_string=None, ssl=False): + context['method'] = method + context['path'] = path + context['headers'] = headers or {} + return callback + + def test_sys_meta_headers_PUT(self): + # check that headers in sys meta namespace make it through + # the proxy controller + sys_meta_key = '%stest' % get_sys_meta_prefix('account') + sys_meta_key = sys_meta_key.title() + user_meta_key = 'X-Account-Meta-Test' + # allow PUTs to account... + self.app.allow_account_management = True + controller = proxy_server.AccountController(self.app, 'a') + context = {} + callback = self._make_callback_func(context) + hdrs_in = {sys_meta_key: 'foo', + user_meta_key: 'bar', + 'x-timestamp': '1.0'} + req = Request.blank('/v1/a', headers=hdrs_in) + with mock.patch('swift.proxy.controllers.base.http_connect', + fake_http_connect(200, 200, give_connect=callback)): + controller.PUT(req) + self.assertEqual(context['method'], 'PUT') + self.assertTrue(sys_meta_key in context['headers']) + self.assertEqual(context['headers'][sys_meta_key], 'foo') + self.assertTrue(user_meta_key in context['headers']) + self.assertEqual(context['headers'][user_meta_key], 'bar') + self.assertNotEqual(context['headers']['x-timestamp'], '1.0') + + def test_sys_meta_headers_POST(self): + # check that headers in sys meta namespace make it through + # the proxy controller + sys_meta_key = '%stest' % get_sys_meta_prefix('account') + sys_meta_key = sys_meta_key.title() + user_meta_key = 'X-Account-Meta-Test' + controller = proxy_server.AccountController(self.app, 'a') + context = {} + callback = self._make_callback_func(context) + hdrs_in = {sys_meta_key: 'foo', + user_meta_key: 'bar', + 'x-timestamp': '1.0'} + req = Request.blank('/v1/a', headers=hdrs_in) + with mock.patch('swift.proxy.controllers.base.http_connect', + fake_http_connect(200, 200, give_connect=callback)): + controller.POST(req) + self.assertEqual(context['method'], 'POST') + self.assertTrue(sys_meta_key in context['headers']) + self.assertEqual(context['headers'][sys_meta_key], 'foo') + self.assertTrue(user_meta_key in context['headers']) + self.assertEqual(context['headers'][user_meta_key], 'bar') + self.assertNotEqual(context['headers']['x-timestamp'], '1.0') + if __name__ == '__main__': unittest.main() diff --git a/test/unit/proxy/controllers/test_base.py b/test/unit/proxy/controllers/test_base.py index 8214b98..0c94f90 100644 --- a/test/unit/proxy/controllers/test_base.py +++ b/test/unit/proxy/controllers/test_base.py @@ -18,11 +18,13 @@ from mock import patch from swift.proxy.controllers.base import headers_to_container_info, \ headers_to_account_info, headers_to_object_info, get_container_info, \ get_container_memcache_key, get_account_info, get_account_memcache_key, \ - get_object_env_key, _get_cache_key, get_info, get_object_info, Controller -from swift.common.swob import Request + get_object_env_key, _get_cache_key, get_info, get_object_info, \ + Controller, GetOrHeadHandler +from swift.common.swob import Request, HTTPException, HeaderKeyDict from swift.common.utils import split_path from test.unit import fake_http_connect, FakeRing, FakeMemcache from swift.proxy import server as proxy_server +from swift.common.request_helpers import get_sys_meta_prefix FakeResponse_status_int = 201 @@ -88,7 +90,7 @@ class TestFuncs(unittest.TestCase): def test_GETorHEAD_base(self): base = Controller(self.app) - req = Request.blank('/a/c/o/with/slashes') + req = Request.blank('/v1/a/c/o/with/slashes') with patch('swift.proxy.controllers.base.' 'http_connect', fake_http_connect(200)): resp = base.GETorHEAD_base(req, 'object', FakeRing(), 'part', @@ -96,14 +98,14 @@ class TestFuncs(unittest.TestCase): self.assertTrue('swift.object/a/c/o/with/slashes' in resp.environ) self.assertEqual( resp.environ['swift.object/a/c/o/with/slashes']['status'], 200) - req = Request.blank('/a/c/o') + req = Request.blank('/v1/a/c/o') with patch('swift.proxy.controllers.base.' 'http_connect', fake_http_connect(200)): resp = base.GETorHEAD_base(req, 'object', FakeRing(), 'part', '/a/c/o') self.assertTrue('swift.object/a/c/o' in resp.environ) self.assertEqual(resp.environ['swift.object/a/c/o']['status'], 200) - req = Request.blank('/a/c') + req = Request.blank('/v1/a/c') with patch('swift.proxy.controllers.base.' 'http_connect', fake_http_connect(200)): resp = base.GETorHEAD_base(req, 'container', FakeRing(), 'part', @@ -111,7 +113,7 @@ class TestFuncs(unittest.TestCase): self.assertTrue('swift.container/a/c' in resp.environ) self.assertEqual(resp.environ['swift.container/a/c']['status'], 200) - req = Request.blank('/a') + req = Request.blank('/v1/a') with patch('swift.proxy.controllers.base.' 'http_connect', fake_http_connect(200)): resp = base.GETorHEAD_base(req, 'account', FakeRing(), 'part', @@ -250,7 +252,9 @@ class TestFuncs(unittest.TestCase): def test_get_container_info_cache(self): cached = {'status': 404, 'bytes': 3333, - 'object_count': 10} + 'object_count': 10, + # simplejson sometimes hands back strings, sometimes unicodes + 'versions': u"\u1F4A9"} req = Request.blank("/v1/account/cont", environ={'swift.cache': FakeCache(cached)}) with patch('swift.proxy.controllers.base.' @@ -259,6 +263,7 @@ class TestFuncs(unittest.TestCase): self.assertEquals(resp['bytes'], 3333) self.assertEquals(resp['object_count'], 10) self.assertEquals(resp['status'], 404) + self.assertEquals(resp['versions'], "\xe1\xbd\x8a\x39") def test_get_container_info_env(self): cache_key = get_container_memcache_key("account", "cont") @@ -361,6 +366,15 @@ class TestFuncs(unittest.TestCase): self.assertEquals(resp['meta']['whatevs'], 14) self.assertEquals(resp['meta']['somethingelse'], 0) + def test_headers_to_container_info_sys_meta(self): + prefix = get_sys_meta_prefix('container') + headers = {'%sWhatevs' % prefix: 14, + '%ssomethingelse' % prefix: 0} + resp = headers_to_container_info(headers.items(), 200) + self.assertEquals(len(resp['sysmeta']), 2) + self.assertEquals(resp['sysmeta']['whatevs'], 14) + self.assertEquals(resp['sysmeta']['somethingelse'], 0) + def test_headers_to_container_info_values(self): headers = { 'x-container-read': 'readvalue', @@ -392,6 +406,15 @@ class TestFuncs(unittest.TestCase): self.assertEquals(resp['meta']['whatevs'], 14) self.assertEquals(resp['meta']['somethingelse'], 0) + def test_headers_to_account_info_sys_meta(self): + prefix = get_sys_meta_prefix('account') + headers = {'%sWhatevs' % prefix: 14, + '%ssomethingelse' % prefix: 0} + resp = headers_to_account_info(headers.items(), 200) + self.assertEquals(len(resp['sysmeta']), 2) + self.assertEquals(resp['sysmeta']['whatevs'], 14) + self.assertEquals(resp['sysmeta']['somethingelse'], 0) + def test_headers_to_account_info_values(self): headers = { 'x-account-object-count': '10', @@ -433,3 +456,79 @@ class TestFuncs(unittest.TestCase): self.assertEquals( resp, headers_to_object_info(headers.items(), 200)) + + def test_have_quorum(self): + base = Controller(self.app) + # just throw a bunch of test cases at it + self.assertEqual(base.have_quorum([201, 404], 3), False) + self.assertEqual(base.have_quorum([201, 201], 4), False) + self.assertEqual(base.have_quorum([201, 201, 404, 404], 4), False) + self.assertEqual(base.have_quorum([201, 503, 503, 201], 4), False) + self.assertEqual(base.have_quorum([201, 201], 3), True) + self.assertEqual(base.have_quorum([404, 404], 3), True) + self.assertEqual(base.have_quorum([201, 201], 2), True) + self.assertEqual(base.have_quorum([404, 404], 2), True) + self.assertEqual(base.have_quorum([201, 404, 201, 201], 4), True) + + def test_range_fast_forward(self): + req = Request.blank('/') + handler = GetOrHeadHandler(None, req, None, None, None, None, {}) + handler.fast_forward(50) + self.assertEquals(handler.backend_headers['Range'], 'bytes=50-') + + handler = GetOrHeadHandler(None, req, None, None, None, None, + {'Range': 'bytes=23-50'}) + handler.fast_forward(20) + self.assertEquals(handler.backend_headers['Range'], 'bytes=43-50') + self.assertRaises(HTTPException, + handler.fast_forward, 80) + + handler = GetOrHeadHandler(None, req, None, None, None, None, + {'Range': 'bytes=23-'}) + handler.fast_forward(20) + self.assertEquals(handler.backend_headers['Range'], 'bytes=43-') + + handler = GetOrHeadHandler(None, req, None, None, None, None, + {'Range': 'bytes=-100'}) + handler.fast_forward(20) + self.assertEquals(handler.backend_headers['Range'], 'bytes=-80') + + def test_transfer_headers_with_sysmeta(self): + base = Controller(self.app) + good_hdrs = {'x-base-sysmeta-foo': 'ok', + 'X-Base-sysmeta-Bar': 'also ok'} + bad_hdrs = {'x-base-sysmeta-': 'too short'} + hdrs = dict(good_hdrs) + hdrs.update(bad_hdrs) + dst_hdrs = HeaderKeyDict() + base.transfer_headers(hdrs, dst_hdrs) + self.assertEqual(HeaderKeyDict(good_hdrs), dst_hdrs) + + def test_generate_request_headers(self): + base = Controller(self.app) + src_headers = {'x-remove-base-meta-owner': 'x', + 'x-base-meta-size': '151M', + 'new-owner': 'Kun'} + req = Request.blank('/v1/a/c/o', headers=src_headers) + dst_headers = base.generate_request_headers(req, transfer=True) + expected_headers = {'x-base-meta-owner': '', + 'x-base-meta-size': '151M'} + for k, v in expected_headers.iteritems(): + self.assertTrue(k in dst_headers) + self.assertEqual(v, dst_headers[k]) + self.assertFalse('new-owner' in dst_headers) + + def test_generate_request_headers_with_sysmeta(self): + base = Controller(self.app) + good_hdrs = {'x-base-sysmeta-foo': 'ok', + 'X-Base-sysmeta-Bar': 'also ok'} + bad_hdrs = {'x-base-sysmeta-': 'too short'} + hdrs = dict(good_hdrs) + hdrs.update(bad_hdrs) + req = Request.blank('/v1/a/c/o', headers=hdrs) + dst_headers = base.generate_request_headers(req, transfer=True) + for k, v in good_hdrs.iteritems(): + self.assertTrue(k.lower() in dst_headers) + self.assertEqual(v, dst_headers[k.lower()]) + for k, v in bad_hdrs.iteritems(): + self.assertFalse(k.lower() in dst_headers) diff --git a/test/unit/proxy/controllers/test_container.py b/test/unit/proxy/controllers/test_container.py index 63e6b0e..7c8ecf7 100644 --- a/test/unit/proxy/controllers/test_container.py +++ b/test/unit/proxy/controllers/test_container.py @@ -20,6 +20,7 @@ from swift.common.swob import Request from swift.proxy import server as proxy_server from swift.proxy.controllers.base import headers_to_container_info from test.unit import fake_http_connect, FakeRing, FakeMemcache +from swift.common.request_helpers import get_sys_meta_prefix class TestContainerController(unittest.TestCase): @@ -33,7 +34,7 @@ class TestContainerController(unittest.TestCase): controller = proxy_server.ContainerController(self.app, 'a', 'c') with mock.patch('swift.proxy.controllers.base.http_connect', fake_http_connect(200, 200, body='')): - req = Request.blank('/a/c', {'PATH_INFO': '/a/c'}) + req = Request.blank('/v1/a/c', {'PATH_INFO': '/v1/a/c'}) resp = controller.HEAD(req) self.assertEqual(2, resp.status_int // 100) self.assertTrue("swift.container/a/c" in resp.environ) @@ -46,7 +47,7 @@ class TestContainerController(unittest.TestCase): 'x-container-sync-key': 'value', 'x-container-sync-to': 'value'} controller = proxy_server.ContainerController(self.app, 'a', 'c') - req = Request.blank('/a/c') + req = Request.blank('/v1/a/c') with mock.patch('swift.proxy.controllers.base.http_connect', fake_http_connect(200, 200, headers=owner_headers)): resp = controller.HEAD(req) @@ -54,7 +55,7 @@ class TestContainerController(unittest.TestCase): for key in owner_headers: self.assertTrue(key not in resp.headers) - req = Request.blank('/a/c', environ={'swift_owner': True}) + req = Request.blank('/v1/a/c', environ={'swift_owner': True}) with mock.patch('swift.proxy.controllers.base.http_connect', fake_http_connect(200, 200, headers=owner_headers)): resp = controller.HEAD(req) @@ -62,6 +63,61 @@ class TestContainerController(unittest.TestCase): for key in owner_headers: self.assertTrue(key in resp.headers) + def _make_callback_func(self, context): + def callback(ipaddr, port, device, partition, method, path, + headers=None, query_string=None, ssl=False): + context['method'] = method + context['path'] = path + context['headers'] = headers or {} + return callback + + def test_sys_meta_headers_PUT(self): + # check that headers in sys meta namespace make it through + # the container controller + sys_meta_key = '%stest' % get_sys_meta_prefix('container') + sys_meta_key = sys_meta_key.title() + user_meta_key = 'X-Container-Meta-Test' + controller = proxy_server.ContainerController(self.app, 'a', 'c') + + context = {} + callback = self._make_callback_func(context) + hdrs_in = {sys_meta_key: 'foo', + user_meta_key: 'bar', + 'x-timestamp': '1.0'} + req = Request.blank('/v1/a/c', headers=hdrs_in) + with mock.patch('swift.proxy.controllers.base.http_connect', + fake_http_connect(200, 200, give_connect=callback)): + controller.PUT(req) + self.assertEqual(context['method'], 'PUT') + self.assertTrue(sys_meta_key in context['headers']) + self.assertEqual(context['headers'][sys_meta_key], 'foo') + self.assertTrue(user_meta_key in context['headers']) + self.assertEqual(context['headers'][user_meta_key], 'bar') + self.assertNotEqual(context['headers']['x-timestamp'], '1.0') + + def test_sys_meta_headers_POST(self): + # check that headers in sys meta namespace make it through + # the container controller + sys_meta_key = '%stest' % get_sys_meta_prefix('container') + sys_meta_key = sys_meta_key.title() + user_meta_key = 'X-Container-Meta-Test' + controller = proxy_server.ContainerController(self.app, 'a', 'c') + context = {} + callback = self._make_callback_func(context) + hdrs_in = {sys_meta_key: 'foo', + user_meta_key: 'bar', + 'x-timestamp': '1.0'} + req = Request.blank('/v1/a/c', headers=hdrs_in) + with mock.patch('swift.proxy.controllers.base.http_connect', + fake_http_connect(200, 200, give_connect=callback)): + controller.POST(req) + self.assertEqual(context['method'], 'POST') + self.assertTrue(sys_meta_key in context['headers']) + self.assertEqual(context['headers'][sys_meta_key], 'foo') + self.assertTrue(user_meta_key in context['headers']) + self.assertEqual(context['headers'][user_meta_key], 'bar') + self.assertNotEqual(context['headers']['x-timestamp'], '1.0') + if __name__ == '__main__': unittest.main() diff --git a/test/unit/proxy/controllers/test_info.py b/test/unit/proxy/controllers/test_info.py new file mode 100644 index 0000000..f33beba --- /dev/null +++ b/test/unit/proxy/controllers/test_info.py @@ -0,0 +1,293 @@ +# Copyright (c) 2010-2012 OpenStack Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import time +from mock import Mock + +from swift.proxy.controllers import InfoController +from swift.proxy.server import Application as ProxyApp +from swift.common import utils +from swift.common.utils import json +from swift.common.swob import Request, HTTPException + + +class TestInfoController(unittest.TestCase): + + def setUp(self): + utils._swift_info = {} + utils._swift_admin_info = {} + + def get_controller(self, expose_info=None, disallowed_sections=None, + admin_key=None): + disallowed_sections = disallowed_sections or [] + + app = Mock(spec=ProxyApp) + return InfoController(app, None, expose_info, + disallowed_sections, admin_key) + + def start_response(self, status, headers): + self.got_statuses.append(status) + for h in headers: + self.got_headers.append({h[0]: h[1]}) + + def test_disabled_info(self): + controller = self.get_controller(expose_info=False) + + req = Request.blank( + '/info', environ={'REQUEST_METHOD': 'GET'}) + resp = controller.GET(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('403 Forbidden', str(resp)) + + def test_get_info(self): + controller = self.get_controller(expose_info=True) + utils._swift_info = {'foo': {'bar': 'baz'}} + utils._swift_admin_info = {'qux': {'quux': 'corge'}} + + req = Request.blank( + '/info', environ={'REQUEST_METHOD': 'GET'}) + resp = controller.GET(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('200 OK', str(resp)) + info = json.loads(resp.body) + self.assertTrue('admin' not in info) + self.assertTrue('foo' in info) + self.assertTrue('bar' in info['foo']) + self.assertEqual(info['foo']['bar'], 'baz') + + def test_options_info(self): + controller = self.get_controller(expose_info=True) + + req = Request.blank( + '/info', environ={'REQUEST_METHOD': 'GET'}) + resp = controller.OPTIONS(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('200 OK', str(resp)) + self.assertTrue('Allow' in resp.headers) + + def test_get_info_cors(self): + controller = self.get_controller(expose_info=True) + utils._swift_info = {'foo': {'bar': 'baz'}} + utils._swift_admin_info = {'qux': {'quux': 'corge'}} + + req = Request.blank( + '/info', environ={'REQUEST_METHOD': 'GET'}, + headers={'Origin': 'http://example.com'}) + resp = controller.GET(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('200 OK', str(resp)) + info = json.loads(resp.body) + self.assertTrue('admin' not in info) + self.assertTrue('foo' in info) + self.assertTrue('bar' in info['foo']) + self.assertEqual(info['foo']['bar'], 'baz') + self.assertTrue('Access-Control-Allow-Origin' in resp.headers) + self.assertTrue('Access-Control-Expose-Headers' in resp.headers) + + def test_head_info(self): + controller = self.get_controller(expose_info=True) + utils._swift_info = {'foo': {'bar': 'baz'}} + utils._swift_admin_info = {'qux': {'quux': 'corge'}} + + req = Request.blank( + '/info', environ={'REQUEST_METHOD': 'HEAD'}) + resp = controller.HEAD(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('200 OK', str(resp)) + + def test_disallow_info(self): + controller = self.get_controller(expose_info=True, + disallowed_sections=['foo2']) + utils._swift_info = {'foo': {'bar': 'baz'}, + 'foo2': {'bar2': 'baz2'}} + utils._swift_admin_info = {'qux': {'quux': 'corge'}} + + req = Request.blank( + '/info', environ={'REQUEST_METHOD': 'GET'}) + resp = controller.GET(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('200 OK', str(resp)) + info = json.loads(resp.body) + self.assertTrue('foo' in info) + self.assertTrue('bar' in info['foo']) + self.assertEqual(info['foo']['bar'], 'baz') + self.assertTrue('foo2' not in info) + + def test_disabled_admin_info(self): + controller = self.get_controller(expose_info=True, admin_key='') + utils._swift_info = {'foo': {'bar': 'baz'}} + utils._swift_admin_info = {'qux': {'quux': 'corge'}} + + expires = int(time.time() + 86400) + sig = utils.get_hmac('GET', '/info', expires, '') + path = '/info?swiftinfo_sig={sig}&swiftinfo_expires={expires}'.format( + sig=sig, expires=expires) + req = Request.blank( + path, environ={'REQUEST_METHOD': 'GET'}) + resp = controller.GET(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('403 Forbidden', str(resp)) + + def test_get_admin_info(self): + controller = self.get_controller(expose_info=True, + admin_key='secret-admin-key') + utils._swift_info = {'foo': {'bar': 'baz'}} + utils._swift_admin_info = {'qux': {'quux': 'corge'}} + + expires = int(time.time() + 86400) + sig = utils.get_hmac('GET', '/info', expires, 'secret-admin-key') + path = '/info?swiftinfo_sig={sig}&swiftinfo_expires={expires}'.format( + sig=sig, expires=expires) + req = Request.blank( + path, environ={'REQUEST_METHOD': 'GET'}) + resp = controller.GET(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('200 OK', str(resp)) + info = json.loads(resp.body) + self.assertTrue('admin' in info) + self.assertTrue('qux' in info['admin']) + self.assertTrue('quux' in info['admin']['qux']) + self.assertEqual(info['admin']['qux']['quux'], 'corge') + + def test_head_admin_info(self): + controller = self.get_controller(expose_info=True, + admin_key='secret-admin-key') + utils._swift_info = {'foo': {'bar': 'baz'}} + utils._swift_admin_info = {'qux': {'quux': 'corge'}} + + expires = int(time.time() + 86400) + sig = utils.get_hmac('GET', '/info', expires, 'secret-admin-key') + path = '/info?swiftinfo_sig={sig}&swiftinfo_expires={expires}'.format( + sig=sig, expires=expires) + req = Request.blank( + path, environ={'REQUEST_METHOD': 'HEAD'}) + resp = controller.GET(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('200 OK', str(resp)) + + expires = int(time.time() + 86400) + sig = utils.get_hmac('HEAD', '/info', expires, 'secret-admin-key') + path = '/info?swiftinfo_sig={sig}&swiftinfo_expires={expires}'.format( + sig=sig, expires=expires) + req = Request.blank( + path, environ={'REQUEST_METHOD': 'HEAD'}) + resp = controller.GET(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('200 OK', str(resp)) + + def test_get_admin_info_invalid_method(self): + controller = self.get_controller(expose_info=True, + admin_key='secret-admin-key') + utils._swift_info = {'foo': {'bar': 'baz'}} + utils._swift_admin_info = {'qux': {'quux': 'corge'}} + + expires = int(time.time() + 86400) + sig = utils.get_hmac('HEAD', '/info', expires, 'secret-admin-key') + path = '/info?swiftinfo_sig={sig}&swiftinfo_expires={expires}'.format( + sig=sig, expires=expires) + req = Request.blank( + path, environ={'REQUEST_METHOD': 'GET'}) + resp = controller.GET(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('401 Unauthorized', str(resp)) + + def test_get_admin_info_invalid_expires(self): + controller = self.get_controller(expose_info=True, + admin_key='secret-admin-key') + utils._swift_info = {'foo': {'bar': 'baz'}} + utils._swift_admin_info = {'qux': {'quux': 'corge'}} + + expires = 1 + sig = utils.get_hmac('GET', '/info', expires, 'secret-admin-key') + path = '/info?swiftinfo_sig={sig}&swiftinfo_expires={expires}'.format( + sig=sig, expires=expires) + req = Request.blank( + path, environ={'REQUEST_METHOD': 'GET'}) + resp = controller.GET(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('401 Unauthorized', str(resp)) + + expires = 'abc' + sig = utils.get_hmac('GET', '/info', expires, 'secret-admin-key') + path = '/info?swiftinfo_sig={sig}&swiftinfo_expires={expires}'.format( + sig=sig, expires=expires) + req = Request.blank( + path, environ={'REQUEST_METHOD': 'GET'}) + resp = controller.GET(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('401 Unauthorized', str(resp)) + + def test_get_admin_info_invalid_path(self): + controller = self.get_controller(expose_info=True, + admin_key='secret-admin-key') + utils._swift_info = {'foo': {'bar': 'baz'}} + utils._swift_admin_info = {'qux': {'quux': 'corge'}} + + expires = int(time.time() + 86400) + sig = utils.get_hmac('GET', '/foo', expires, 'secret-admin-key') + path = '/info?swiftinfo_sig={sig}&swiftinfo_expires={expires}'.format( + sig=sig, expires=expires) + req = Request.blank( + path, environ={'REQUEST_METHOD': 'GET'}) + resp = controller.GET(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('401 Unauthorized', str(resp)) + + def test_get_admin_info_invalid_key(self): + controller = self.get_controller(expose_info=True, + admin_key='secret-admin-key') + utils._swift_info = {'foo': {'bar': 'baz'}} + utils._swift_admin_info = {'qux': {'quux': 'corge'}} + + expires = int(time.time() + 86400) + sig = utils.get_hmac('GET', '/foo', expires, 'invalid-admin-key') + path = '/info?swiftinfo_sig={sig}&swiftinfo_expires={expires}'.format( + sig=sig, expires=expires) + req = Request.blank( + path, environ={'REQUEST_METHOD': 'GET'}) + resp = controller.GET(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('401 Unauthorized', str(resp)) + + def test_admin_disallow_info(self): + controller = self.get_controller(expose_info=True, + disallowed_sections=['foo2'], + admin_key='secret-admin-key') + utils._swift_info = {'foo': {'bar': 'baz'}, + 'foo2': {'bar2': 'baz2'}} + utils._swift_admin_info = {'qux': {'quux': 'corge'}} + + expires = int(time.time() + 86400) + sig = utils.get_hmac('GET', '/info', expires, 'secret-admin-key') + path = '/info?swiftinfo_sig={sig}&swiftinfo_expires={expires}'.format( + sig=sig, expires=expires) + req = Request.blank( + path, environ={'REQUEST_METHOD': 'GET'}) + resp = controller.GET(req) + self.assertTrue(isinstance(resp, HTTPException)) + self.assertEqual('200 OK', str(resp)) + info = json.loads(resp.body) + self.assertTrue('foo2' not in info) + self.assertTrue('admin' in info) + self.assertTrue('disallowed_sections' in info['admin']) + self.assertTrue('foo2' in info['admin']['disallowed_sections']) + self.assertTrue('qux' in info['admin']) + self.assertTrue('quux' in info['admin']['qux']) + self.assertEqual(info['admin']['qux']['quux'], 'corge') + + +if __name__ == '__main__': + unittest.main() diff --git a/test/unit/proxy/test_server.py b/test/unit/proxy/test_server.py index 4c75562..f669b9d 100644 --- a/test/unit/proxy/test_server.py +++ b/test/unit/proxy/test_server.py @@ -39,16 +39,18 @@ import gluster.swift.common.Glusterfs as gfs gfs.RUN_DIR = mkdtemp() from test.unit import connect_tcp, readuntil2crlfs, FakeLogger, \ - fake_http_connect, FakeRing, FakeMemcache, DebugLogger + fake_http_connect, FakeRing, FakeMemcache, debug_logger from gluster.swift.proxy import server as proxy_server from gluster.swift.account import server as account_server from gluster.swift.container import server as container_server from gluster.swift.obj import server as object_server from swift.common import ring +from swift.common.middleware import proxy_logging from swift.common.exceptions import ChunkReadTimeout, SegmentError from swift.common.constraints import MAX_META_NAME_LENGTH, \ MAX_META_VALUE_LENGTH, MAX_META_COUNT, MAX_META_OVERALL_SIZE, \ - MAX_FILE_SIZE, MAX_ACCOUNT_NAME_LENGTH, MAX_CONTAINER_NAME_LENGTH + MAX_FILE_SIZE, MAX_ACCOUNT_NAME_LENGTH, MAX_CONTAINER_NAME_LENGTH, \ + ACCOUNT_LISTING_LIMIT, CONTAINER_LISTING_LIMIT, MAX_OBJECT_NAME_LENGTH from swift.common import utils from swift.common.utils import mkdirs, normalize_timestamp, NullLogger from swift.common.wsgi import monkey_patch_mimetools @@ -144,17 +146,26 @@ def do_setup(the_object_server): {'id': 1, 'zone': 1, 'device': 'a', 'ip': '127.0.0.1', 'port': obj2lis.getsockname()[1]}], 30), f) - prosrv = proxy_server.Application(conf, FakeMemcacheReturnsNone()) - acc1srv = account_server.AccountController(conf) - acc2srv = account_server.AccountController(conf) - con1srv = container_server.ContainerController(conf) - con2srv = container_server.ContainerController(conf) - obj1srv = the_object_server.ObjectController(conf) - obj2srv = the_object_server.ObjectController(conf) + prosrv = proxy_server.Application(conf, FakeMemcacheReturnsNone(), + logger=debug_logger('proxy')) + acc1srv = account_server.AccountController( + conf, logger=debug_logger('acct1')) + acc2srv = account_server.AccountController( + conf, logger=debug_logger('acct2')) + con1srv = container_server.ContainerController( + conf, logger=debug_logger('cont1')) + con2srv = container_server.ContainerController( + conf, logger=debug_logger('cont2')) + obj1srv = the_object_server.ObjectController( + conf, logger=debug_logger('obj1')) + obj2srv = the_object_server.ObjectController( + conf, logger=debug_logger('obj2')) _test_servers = \ (prosrv, acc1srv, acc2srv, con1srv, con2srv, obj1srv, obj2srv) - nl = DebugLogger() - prospa = spawn(wsgi.server, prolis, prosrv, nl) + nl = NullLogger() + logging_prosv = proxy_logging.ProxyLoggingMiddleware(prosrv, conf, + logger=prosrv.logger) + prospa = spawn(wsgi.server, prolis, logging_prosv, nl) acc1spa = spawn(wsgi.server, acc1lis, acc1srv, nl) acc2spa = spawn(wsgi.server, acc2lis, acc2srv, nl) con1spa = spawn(wsgi.server, con1lis, con1srv, nl) @@ -348,7 +359,8 @@ class TestController(unittest.TestCase): 'container_count': '12345', 'total_object_count': None, 'bytes': None, - 'meta': {}} + 'meta': {}, + 'sysmeta': {}} self.assertEquals(container_info, self.memcache.get(cache_key)) @@ -374,7 +386,8 @@ class TestController(unittest.TestCase): 'container_count': None, # internally keep None 'total_object_count': None, 'bytes': None, - 'meta': {}} + 'meta': {}, + 'sysmeta': {}} self.assertEquals(account_info, self.memcache.get(cache_key)) @@ -523,7 +536,7 @@ class TestProxyServer(unittest.TestCase): app = MyApp(None, FakeMemcache(), account_ring=FakeRing(), container_ring=FakeRing(), object_ring=FakeRing()) - req = Request.blank('/account', environ={'REQUEST_METHOD': 'HEAD'}) + req = Request.blank('/v1/account', environ={'REQUEST_METHOD': 'HEAD'}) app.update_request(req) resp = app.handle_request(req) self.assertEquals(resp.status_int, 500) @@ -710,7 +723,7 @@ class TestObjectController(unittest.TestCase): set_http_connect(*statuses, **kwargs) self.app.memcache.store = {} - req = Request.blank('/a/c/o', + req = Request.blank('/v1/a/c/o', headers={'Content-Length': '0', 'Content-Type': 'text/plain'}) self.app.update_request(req) @@ -720,7 +733,7 @@ class TestObjectController(unittest.TestCase): # repeat test set_http_connect(*statuses, **kwargs) self.app.memcache.store = {} - req = Request.blank('/a/c/o', + req = Request.blank('/v1/a/c/o', headers={'Content-Length': '0', 'Content-Type': 'text/plain'}) self.app.update_request(req) @@ -773,7 +786,7 @@ class TestObjectController(unittest.TestCase): # 100. Perfectly straightforward. set_http_connect(200, 200, (201, -4), (201, -4), (201, -4), give_connect=test_connect) - req = Request.blank('/a/c/o.jpg', {}) + req = Request.blank('/v1/a/c/o.jpg', {}) req.content_length = 0 self.app.update_request(req) self.app.memcache.store = {} @@ -796,7 +809,7 @@ class TestObjectController(unittest.TestCase): proxy_server.ObjectController(self.app, 'a', 'c', 'o.jpg') set_http_connect(200, 200, 201, 201, 201, give_connect=test_connect) - req = Request.blank('/a/c/o.jpg', {}) + req = Request.blank('/v1/a/c/o.jpg', {}) req.content_length = 1 req.body = 'a' self.app.update_request(req) @@ -824,7 +837,7 @@ class TestObjectController(unittest.TestCase): proxy_server.ObjectController(self.app, 'a', 'c', 'o.jpg') set_http_connect(200, 200, 201, 201, 201, give_connect=test_connect) - req = Request.blank('/a/c/o.jpg', {}) + req = Request.blank('/v1/a/c/o.jpg', {}) req.content_length = 1 req.body = 'a' self.app.memcache.store = {} @@ -861,7 +874,7 @@ class TestObjectController(unittest.TestCase): set_http_connect(200, 200, # account, container 201, 201, 201, # 3 working backends give_connect=test_connect) - req = Request.blank('/a/c/o.jpg', {}) + req = Request.blank('/v1/a/c/o.jpg', {}) req.content_length = 1 req.body = 'a' self.app.memcache.store = {} @@ -1044,6 +1057,56 @@ class TestObjectController(unittest.TestCase): finally: swift.proxy.controllers.obj.MAX_FILE_SIZE = MAX_FILE_SIZE + def test_PUT_last_modified(self): + prolis = _test_sockets[0] + sock = connect_tcp(('localhost', prolis.getsockname()[1])) + fd = sock.makefile() + fd.write('PUT /v1/a/c/o.last_modified HTTP/1.1\r\n' + 'Host: localhost\r\nConnection: close\r\n' + 'X-Storage-Token: t\r\nContent-Length: 0\r\n\r\n') + fd.flush() + headers = readuntil2crlfs(fd) + exp = 'HTTP/1.1 201' + lm_hdr = 'Last-Modified: ' + self.assertEqual(headers[:len(exp)], exp) + + last_modified_put = [line for line in headers.split('\r\n') + if lm_hdr in line][0][len(lm_hdr):] + sock = connect_tcp(('localhost', prolis.getsockname()[1])) + fd = sock.makefile() + fd.write('HEAD /v1/a/c/o.last_modified HTTP/1.1\r\n' + 'Host: localhost\r\nConnection: close\r\n' + 'X-Storage-Token: t\r\n\r\n') + fd.flush() + headers = readuntil2crlfs(fd) + exp = 'HTTP/1.1 200' + self.assertEqual(headers[:len(exp)], exp) + last_modified_head = [line for line in headers.split('\r\n') + if lm_hdr in line][0][len(lm_hdr):] + self.assertEqual(last_modified_put, last_modified_head) + + sock = connect_tcp(('localhost', prolis.getsockname()[1])) + fd = sock.makefile() + fd.write('GET /v1/a/c/o.last_modified HTTP/1.1\r\n' + 'Host: localhost\r\nConnection: close\r\n' + 'If-Modified-Since: %s\r\n' + 'X-Storage-Token: t\r\n\r\n' % last_modified_put) + fd.flush() + headers = readuntil2crlfs(fd) + exp = 'HTTP/1.1 304' + self.assertEqual(headers[:len(exp)], exp) + + sock = connect_tcp(('localhost', prolis.getsockname()[1])) + fd = sock.makefile() + fd.write('GET /v1/a/c/o.last_modified HTTP/1.1\r\n' + 'Host: localhost\r\nConnection: close\r\n' + 'If-Unmodified-Since: %s\r\n' + 'X-Storage-Token: t\r\n\r\n' % last_modified_put) + fd.flush() + headers = readuntil2crlfs(fd) + exp = 'HTTP/1.1 200' + self.assertEqual(headers[:len(exp)], exp) + def test_expirer_DELETE_on_versioned_object(self): test_errors = [] @@ -1070,7 +1133,7 @@ class TestObjectController(unittest.TestCase): body_iter=body_iter, headers={'x-versions-location': 'foo'}) self.app.memcache.store = {} - req = Request.blank('/a/c/o', + req = Request.blank('/v1/a/c/o', headers={'X-If-Delete-At': 1}, environ={'REQUEST_METHOD': 'DELETE'}) self.app.update_request(req) @@ -1097,7 +1160,7 @@ class TestObjectController(unittest.TestCase): headers=hdict, body_iter=response_bodies) - req = Request.blank('/a/c/manifest') + req = Request.blank('/v1/a/c/manifest') resp = controller.GET(req) self.assertEqual(resp.status_int, 200) self.assertEqual(resp.body, '') @@ -1176,7 +1239,7 @@ class TestObjectController(unittest.TestCase): body_iter=response_bodies, give_connect=capture_requested_paths) - req = Request.blank('/a/c/manifest') + req = Request.blank('/v1/a/c/manifest') resp = controller.GET(req) self.assertEqual(resp.status_int, 200) self.assertEqual(resp.body, 'AaBbCcDdEe') @@ -1249,7 +1312,7 @@ class TestObjectController(unittest.TestCase): body_iter=response_bodies, give_connect=capture_requested_paths) - req = Request.blank('/a/c/manifest') + req = Request.blank('/v1/a/c/manifest') resp = controller.GET(req) self.assertEqual(resp.status_int, 200) self.assertEqual(resp.body, 'AaBb') @@ -1301,7 +1364,7 @@ class TestObjectController(unittest.TestCase): body_iter=response_bodies, give_connect=capture_requested_paths) - req = Request.blank('/a/c/manifest?multipart-manifest=get') + req = Request.blank('/v1/a/c/manifest?multipart-manifest=get') resp = controller.GET(req) self.assertEqual(resp.status_int, 200) self.assertEqual(resp.body, json_listing) @@ -1351,7 +1414,7 @@ class TestObjectController(unittest.TestCase): body_iter=response_bodies, give_connect=capture_requested_paths) - req = Request.blank('/a/c/manifest?multipart-manifest=get', + req = Request.blank('/v1/a/c/manifest?multipart-manifest=get', headers={'x-copy-from': '/a/c/manifest'}) resp = controller.GET(req) self.assertEqual(resp.status_int, 200) @@ -1404,7 +1467,7 @@ class TestObjectController(unittest.TestCase): 'content-type': 'text/html; swift_bytes=4'}, {}, {}], body_iter=response_bodies, give_connect=capture_requested_paths) - req = Request.blank('/a/c/manifest') + req = Request.blank('/v1/a/c/manifest') resp = controller.GET(req) self.assertEqual(resp.status_int, 200) self.assertEqual(resp.content_length, 4) # content incomplete @@ -1484,7 +1547,7 @@ class TestObjectController(unittest.TestCase): headers=[{}, {}, slob_headers, slob_headers, {}, {}, {}, {}], body_iter=response_bodies, give_connect=capture_requested_paths) - req = Request.blank('/a/c/manifest') + req = Request.blank('/v1/a/c/manifest') resp = controller.GET(req) self.assertEqual(resp.status_int, 200) self.assertEqual(resp.content_length, 8) @@ -1587,7 +1650,7 @@ class TestObjectController(unittest.TestCase): body_iter=response_bodies, give_connect=capture_requested_paths) - req = Request.blank('/a/c/manifest') + req = Request.blank('/v1/a/c/manifest') req.range = 'bytes=4-7' resp = controller.GET(req) got_called = [False, ] @@ -1659,7 +1722,7 @@ class TestObjectController(unittest.TestCase): 'content-type': 'text/html; swift_bytes=4'}, {}, {}], body_iter=response_bodies, give_connect=capture_requested_paths) - req = Request.blank('/a/c/manifest') + req = Request.blank('/v1/a/c/manifest') resp = controller.GET(req) self.assertEqual(resp.status_int, 200) self.assertEqual(resp.content_length, 6) # content incomplete @@ -1716,7 +1779,7 @@ class TestObjectController(unittest.TestCase): body_iter=response_bodies, give_connect=capture_requested_paths) - req = Request.blank('/a/c/manifest', + req = Request.blank('/v1/a/c/manifest', environ={'REQUEST_METHOD': 'HEAD'}) resp = controller.HEAD(req) self.assertEqual(resp.status_int, 200) @@ -1744,7 +1807,7 @@ class TestObjectController(unittest.TestCase): expected.next())) # We need into include a transfer-encoding to get past # constraints.check_object_creation() - req = Request.blank('/a/c/%s' % filename, {}, + req = Request.blank('/v1/a/c/%s' % filename, {}, headers={'transfer-encoding': 'chunked'}) self.app.update_request(req) self.app.memcache.store = {} @@ -1783,7 +1846,7 @@ class TestObjectController(unittest.TestCase): def test_status_map(statuses, expected): set_http_connect(*statuses) - req = Request.blank('/a/c/o.jpg', {}) + req = Request.blank('/v1/a/c/o.jpg', {}) req.content_length = 0 self.app.update_request(req) self.app.memcache.store = {} @@ -1803,7 +1866,7 @@ class TestObjectController(unittest.TestCase): def test_status_map(statuses, expected): set_http_connect(*statuses) self.app.memcache.store = {} - req = Request.blank('/a/c/o.jpg', {}) + req = Request.blank('/v1/a/c/o.jpg', {}) req.content_length = 0 self.app.update_request(req) res = controller.PUT(req) @@ -1823,7 +1886,7 @@ class TestObjectController(unittest.TestCase): def test_status_map(statuses, expected): self.app.memcache.store = {} set_http_connect(*statuses) - req = Request.blank('/a/c/o.jpg', + req = Request.blank('/v1/a/c/o.jpg', environ={'REQUEST_METHOD': 'PUT'}, body='some data') self.app.update_request(req) @@ -1839,7 +1902,7 @@ class TestObjectController(unittest.TestCase): set_http_connect(201, 201, 201) controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') - req = Request.blank('/a/c/o', {}, headers={ + req = Request.blank('/v1/a/c/o', {}, headers={ 'Content-Length': str(MAX_FILE_SIZE + 1), 'Content-Type': 'foo/bar'}) self.app.update_request(req) @@ -1851,7 +1914,7 @@ class TestObjectController(unittest.TestCase): set_http_connect(201, 201, 201) controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') - req = Request.blank('/a/c/o', {}, headers={ + req = Request.blank('/v1/a/c/o', {}, headers={ 'Content-Length': 0, 'Content-Type': 'foo/bar;swift_hey=45'}) self.app.update_request(req) res = controller.PUT(req) @@ -1866,7 +1929,7 @@ class TestObjectController(unittest.TestCase): def test_status_map(statuses, expected): self.app.memcache.store = {} set_http_connect(*statuses) - req = Request.blank('/a/c/o.jpg', {}) + req = Request.blank('/v1/a/c/o.jpg', {}) req.content_length = 0 self.app.update_request(req) res = controller.PUT(req) @@ -2315,18 +2378,6 @@ class TestObjectController(unittest.TestCase): def test_node_read_timeout_retry(self): with save_globals(): - self.app.account_ring.get_nodes('account') - for dev in self.app.account_ring.devs.values(): - dev['ip'] = '127.0.0.1' - dev['port'] = 1 - self.app.container_ring.get_nodes('account') - for dev in self.app.container_ring.devs.values(): - dev['ip'] = '127.0.0.1' - dev['port'] = 1 - self.app.object_ring.get_nodes('account') - for dev in self.app.object_ring.devs.values(): - dev['ip'] = '127.0.0.1' - dev['port'] = 1 req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'GET'}) self.app.update_request(req) @@ -2522,7 +2573,7 @@ class TestObjectController(unittest.TestCase): def test_best_response_sets_headers(self): controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'GET'}) + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'GET'}) resp = controller.best_response(req, [200] * 3, ['OK'] * 3, [''] * 3, 'Object', headers=[{'X-Test': '1'}, {'X-Test': '2'}, @@ -2532,7 +2583,7 @@ class TestObjectController(unittest.TestCase): def test_best_response_sets_etag(self): controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'GET'}) + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'GET'}) resp = controller.best_response(req, [200] * 3, ['OK'] * 3, [''] * 3, 'Object') self.assertEquals(resp.etag, None) @@ -2561,7 +2612,8 @@ class TestObjectController(unittest.TestCase): def test_proxy_passes_content_length_on_head(self): with save_globals(): - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'HEAD'}) + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'HEAD'}) self.app.update_request(req) controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') @@ -2618,7 +2670,8 @@ class TestObjectController(unittest.TestCase): controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') set_http_connect(200, 200, 200, 200, 200, 200) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'DELETE'}) + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'DELETE'}) self.app.update_request(req) resp = getattr(controller, 'DELETE')(req) self.assertEquals(resp.status_int, 200) @@ -2626,49 +2679,56 @@ class TestObjectController(unittest.TestCase): set_http_connect(404, 404, 404) # acct acct acct # make sure to use a fresh request without cached env - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'DELETE'}) + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'DELETE'}) resp = getattr(controller, 'DELETE')(req) self.assertEquals(resp.status_int, 404) set_http_connect(503, 404, 404) # acct acct acct # make sure to use a fresh request without cached env - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'DELETE'}) + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'DELETE'}) resp = getattr(controller, 'DELETE')(req) self.assertEquals(resp.status_int, 404) set_http_connect(503, 503, 404) # acct acct acct # make sure to use a fresh request without cached env - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'DELETE'}) + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'DELETE'}) resp = getattr(controller, 'DELETE')(req) self.assertEquals(resp.status_int, 404) set_http_connect(503, 503, 503) # acct acct acct # make sure to use a fresh request without cached env - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'DELETE'}) + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'DELETE'}) resp = getattr(controller, 'DELETE')(req) self.assertEquals(resp.status_int, 404) set_http_connect(200, 200, 204, 204, 204) # acct cont obj obj obj # make sure to use a fresh request without cached env - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'DELETE'}) + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'DELETE'}) resp = getattr(controller, 'DELETE')(req) self.assertEquals(resp.status_int, 204) set_http_connect(200, 404, 404, 404) # acct cont cont cont # make sure to use a fresh request without cached env - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'DELETE'}) + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'DELETE'}) resp = getattr(controller, 'DELETE')(req) self.assertEquals(resp.status_int, 404) set_http_connect(200, 503, 503, 503) # acct cont cont cont # make sure to use a fresh request without cached env - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'DELETE'}) + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'DELETE'}) resp = getattr(controller, 'DELETE')(req) self.assertEquals(resp.status_int, 404) @@ -2679,7 +2739,8 @@ class TestObjectController(unittest.TestCase): # acct [isn't actually called since everything # is error limited] # make sure to use a fresh request without cached env - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'DELETE'}) + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'DELETE'}) resp = getattr(controller, 'DELETE')(req) self.assertEquals(resp.status_int, 404) @@ -2692,7 +2753,8 @@ class TestObjectController(unittest.TestCase): # acct cont [isn't actually called since # everything is error limited] # make sure to use a fresh request without cached env - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'DELETE'}) + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'DELETE'}) resp = getattr(controller, 'DELETE')(req) self.assertEquals(resp.status_int, 404) @@ -2704,13 +2766,15 @@ class TestObjectController(unittest.TestCase): 'container', 'object') set_http_connect(200, 404, 404, 404, 200, 200, 200) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}) + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'PUT'}) self.app.update_request(req) resp = controller.PUT(req) self.assertEquals(resp.status_int, 404) set_http_connect(200, 404, 404, 404, 200, 200) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'POST'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'POST'}, headers={'Content-Type': 'text/plain'}) self.app.update_request(req) resp = controller.POST(req) @@ -2722,13 +2786,14 @@ class TestObjectController(unittest.TestCase): controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') set_http_connect(200, 404, 404, 404, 200, 200, 200) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}) + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}) self.app.update_request(req) resp = controller.PUT(req) self.assertEquals(resp.status_int, 404) set_http_connect(200, 404, 404, 404, 200, 200, 200, 200, 200, 200) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'POST'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'POST'}, headers={'Content-Type': 'text/plain'}) self.app.update_request(req) resp = controller.POST(req) @@ -2740,14 +2805,14 @@ class TestObjectController(unittest.TestCase): 'container', 'object') set_http_connect(200, 200, 201, 201, 201) # acct cont obj obj obj - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0'}) self.app.update_request(req) resp = controller.PUT(req) self.assertEquals(resp.status_int, 201) set_http_connect(201, 201, 201) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Object-Meta-' + ('a' * MAX_META_NAME_LENGTH): 'v'}) @@ -2755,7 +2820,7 @@ class TestObjectController(unittest.TestCase): resp = controller.PUT(req) self.assertEquals(resp.status_int, 201) set_http_connect(201, 201, 201) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Object-Meta-' + ('a' * (MAX_META_NAME_LENGTH + 1)): 'v'}) @@ -2764,7 +2829,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.status_int, 400) set_http_connect(201, 201, 201) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Object-Meta-Too-Long': 'a' * MAX_META_VALUE_LENGTH}) @@ -2772,7 +2837,7 @@ class TestObjectController(unittest.TestCase): resp = controller.PUT(req) self.assertEquals(resp.status_int, 201) set_http_connect(201, 201, 201) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Object-Meta-Too-Long': 'a' * (MAX_META_VALUE_LENGTH + 1)}) @@ -2784,7 +2849,7 @@ class TestObjectController(unittest.TestCase): headers = {'Content-Length': '0'} for x in xrange(MAX_META_COUNT): headers['X-Object-Meta-%d' % x] = 'v' - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers=headers) self.app.update_request(req) resp = controller.PUT(req) @@ -2793,7 +2858,7 @@ class TestObjectController(unittest.TestCase): headers = {'Content-Length': '0'} for x in xrange(MAX_META_COUNT + 1): headers['X-Object-Meta-%d' % x] = 'v' - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers=headers) self.app.update_request(req) resp = controller.PUT(req) @@ -2812,7 +2877,7 @@ class TestObjectController(unittest.TestCase): if MAX_META_OVERALL_SIZE - size > 1: headers['X-Object-Meta-a'] = \ 'a' * (MAX_META_OVERALL_SIZE - size - 1) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers=headers) self.app.update_request(req) resp = controller.PUT(req) @@ -2820,7 +2885,7 @@ class TestObjectController(unittest.TestCase): set_http_connect(201, 201, 201) headers['X-Object-Meta-a'] = \ 'a' * (MAX_META_OVERALL_SIZE - size) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers=headers) self.app.update_request(req) resp = controller.PUT(req) @@ -2831,7 +2896,7 @@ class TestObjectController(unittest.TestCase): controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') # initial source object PUT - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0'}) self.app.update_request(req) set_http_connect(200, 200, 201, 201, 201) @@ -2840,7 +2905,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.status_int, 201) # basic copy - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Copy-From': 'c/o'}) self.app.update_request(req) @@ -2852,7 +2917,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.headers['x-copied-from'], 'c/o') # non-zero content length - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '5', 'X-Copy-From': 'c/o'}) self.app.update_request(req) @@ -2863,7 +2928,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.status_int, 400) # extra source path parsing - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Copy-From': 'c/o/o2'}) req.account = 'a' @@ -2875,7 +2940,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.headers['x-copied-from'], 'c/o/o2') # space in soure path - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Copy-From': 'c/o%20o2'}) req.account = 'a' @@ -2887,7 +2952,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.headers['x-copied-from'], 'c/o%20o2') # repeat tests with leading / - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Copy-From': '/c/o'}) self.app.update_request(req) @@ -2898,7 +2963,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.status_int, 201) self.assertEquals(resp.headers['x-copied-from'], 'c/o') - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Copy-From': '/c/o/o2'}) req.account = 'a' @@ -2912,7 +2977,7 @@ class TestObjectController(unittest.TestCase): # negative tests # invalid x-copy-from path - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Copy-From': '/c'}) self.app.update_request(req) @@ -2921,7 +2986,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.status_int // 100, 4) # client error # server error - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Copy-From': '/c/o'}) self.app.update_request(req) @@ -2932,7 +2997,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.status_int, 503) # not found - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Copy-From': '/c/o'}) self.app.update_request(req) @@ -2943,7 +3008,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.status_int, 404) # some missing containers - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Copy-From': '/c/o'}) self.app.update_request(req) @@ -2954,7 +3019,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.status_int, 201) # test object meta data - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Copy-From': '/c/o', 'X-Object-Meta-Ours': 'okay'}) @@ -2970,7 +3035,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.headers.get('x-delete-at'), '9876543210') # copy-from object is too large to fit in target object - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0', 'X-Copy-From': '/c/o'}) self.app.update_request(req) @@ -2993,7 +3058,7 @@ class TestObjectController(unittest.TestCase): def test_COPY(self): with save_globals(): controller = proxy_server.ObjectController(self.app, 'a', 'c', 'o') - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0'}) req.account = 'a' set_http_connect(200, 200, 201, 201, 201) @@ -3001,7 +3066,8 @@ class TestObjectController(unittest.TestCase): resp = controller.PUT(req) self.assertEquals(resp.status_int, 201) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'COPY'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'COPY'}, headers={'Destination': 'c/o'}) req.account = 'a' set_http_connect(200, 200, 200, 200, 200, 201, 201, 201, 200, 200) @@ -3011,7 +3077,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.status_int, 201) self.assertEquals(resp.headers['x-copied-from'], 'c/o') - req = Request.blank('/a/c/o/o2', + req = Request.blank('/v1/a/c/o/o2', environ={'REQUEST_METHOD': 'COPY'}, headers={'Destination': 'c/o'}) req.account = 'a' @@ -3023,7 +3089,8 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.status_int, 201) self.assertEquals(resp.headers['x-copied-from'], 'c/o/o2') - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'COPY'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'COPY'}, headers={'Destination': '/c/o'}) req.account = 'a' controller.object_name = 'o' @@ -3034,7 +3101,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.status_int, 201) self.assertEquals(resp.headers['x-copied-from'], 'c/o') - req = Request.blank('/a/c/o/o2', + req = Request.blank('/v1/a/c/o/o2', environ={'REQUEST_METHOD': 'COPY'}, headers={'Destination': '/c/o'}) req.account = 'a' @@ -3046,7 +3113,8 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.status_int, 201) self.assertEquals(resp.headers['x-copied-from'], 'c/o/o2') - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'COPY'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'COPY'}, headers={'Destination': 'c_o'}) req.account = 'a' controller.object_name = 'o' @@ -3056,7 +3124,8 @@ class TestObjectController(unittest.TestCase): resp = controller.COPY(req) self.assertEquals(resp.status_int, 412) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'COPY'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'COPY'}, headers={'Destination': '/c/o'}) req.account = 'a' controller.object_name = 'o' @@ -3066,7 +3135,8 @@ class TestObjectController(unittest.TestCase): resp = controller.COPY(req) self.assertEquals(resp.status_int, 503) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'COPY'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'COPY'}, headers={'Destination': '/c/o'}) req.account = 'a' controller.object_name = 'o' @@ -3076,7 +3146,8 @@ class TestObjectController(unittest.TestCase): resp = controller.COPY(req) self.assertEquals(resp.status_int, 404) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'COPY'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'COPY'}, headers={'Destination': '/c/o'}) req.account = 'a' controller.object_name = 'o' @@ -3086,7 +3157,8 @@ class TestObjectController(unittest.TestCase): resp = controller.COPY(req) self.assertEquals(resp.status_int, 201) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'COPY'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'COPY'}, headers={'Destination': '/c/o', 'X-Object-Meta-Ours': 'okay'}) req.account = 'a' @@ -3101,7 +3173,8 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.headers.get('x-object-meta-ours'), 'okay') self.assertEquals(resp.headers.get('x-delete-at'), '9876543210') - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'COPY'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'COPY'}, headers={'Destination': '/c/o'}) self.app.update_request(req) @@ -3123,7 +3196,8 @@ class TestObjectController(unittest.TestCase): def test_COPY_newest(self): with save_globals(): controller = proxy_server.ObjectController(self.app, 'a', 'c', 'o') - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'COPY'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'COPY'}, headers={'Destination': '/c/o'}) req.account = 'a' controller.object_name = 'o' @@ -3150,7 +3224,8 @@ class TestObjectController(unittest.TestCase): controller._connect_put_node = fake_connect_put_node set_http_connect(200, 200, 200, 200, 200, 201, 201, 201) self.app.memcache.store = {} - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'COPY'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'COPY'}, headers={'Destination': '/c/o'}) self.app.update_request(req) @@ -3186,7 +3261,8 @@ class TestObjectController(unittest.TestCase): set_http_connect(201, 201, 201, 201) controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'COPY'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'COPY'}, headers={'Transfer-Encoding': 'chunked', 'Content-Type': 'foo/bar'}) @@ -3198,7 +3274,8 @@ class TestObjectController(unittest.TestCase): # test 413 entity to large set_http_connect(201, 201, 201, 201) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'COPY'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'COPY'}, headers={'Transfer-Encoding': 'chunked', 'Content-Type': 'foo/bar'}) req.body_file = ChunkedFile(11) @@ -4290,7 +4367,7 @@ class TestObjectController(unittest.TestCase): # no etag supplied, object servers return success w/ diff values controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '0'}) self.app.update_request(req) set_http_connect(200, 201, 201, 201, @@ -4302,7 +4379,7 @@ class TestObjectController(unittest.TestCase): self.assertEquals(resp.status_int // 100, 5) # server error # req supplies etag, object servers return 422 - mismatch - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={ 'Content-Length': '0', 'ETag': '68b329da9893e34099c7d8ad5cb9c940', @@ -4318,7 +4395,7 @@ class TestObjectController(unittest.TestCase): def test_response_get_accept_ranges_header(self): with save_globals(): - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'GET'}) + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'GET'}) self.app.update_request(req) controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') @@ -4329,7 +4406,8 @@ class TestObjectController(unittest.TestCase): def test_response_head_accept_ranges_header(self): with save_globals(): - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'HEAD'}) + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'HEAD'}) self.app.update_request(req) controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') @@ -4348,7 +4426,7 @@ class TestObjectController(unittest.TestCase): set_http_connect(200, 200, 201, 201, 201) controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') - req = Request.blank('/a/c/o') + req = Request.blank('/v1/a/c/o') req.environ['swift.authorize'] = authorize self.app.update_request(req) controller.GET(req) @@ -4364,7 +4442,7 @@ class TestObjectController(unittest.TestCase): set_http_connect(200, 200, 201, 201, 201) controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') - req = Request.blank('/a/c/o', {'REQUEST_METHOD': 'HEAD'}) + req = Request.blank('/v1/a/c/o', {'REQUEST_METHOD': 'HEAD'}) req.environ['swift.authorize'] = authorize self.app.update_request(req) controller.HEAD(req) @@ -4381,7 +4459,8 @@ class TestObjectController(unittest.TestCase): set_http_connect(200, 200, 201, 201, 201) controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'POST'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'POST'}, headers={'Content-Length': '5'}, body='12345') req.environ['swift.authorize'] = authorize self.app.update_request(req) @@ -4398,7 +4477,8 @@ class TestObjectController(unittest.TestCase): set_http_connect(200, 200, 200, 200, 200, 201, 201, 201) controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'POST'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'POST'}, headers={'Content-Length': '5'}, body='12345') req.environ['swift.authorize'] = authorize self.app.update_request(req) @@ -4415,7 +4495,7 @@ class TestObjectController(unittest.TestCase): set_http_connect(200, 200, 201, 201, 201) controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '5'}, body='12345') req.environ['swift.authorize'] = authorize self.app.update_request(req) @@ -4432,7 +4512,8 @@ class TestObjectController(unittest.TestCase): set_http_connect(200, 200, 200, 200, 200, 201, 201, 201) controller = proxy_server.ObjectController(self.app, 'account', 'container', 'object') - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'COPY'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'COPY'}, headers={'Destination': 'c/o'}) req.environ['swift.authorize'] = authorize self.app.update_request(req) @@ -4450,7 +4531,7 @@ class TestObjectController(unittest.TestCase): try: t = time.time() time.time = lambda: t - req = Request.blank('/a/c/o', {}, + req = Request.blank('/v1/a/c/o', {}, headers={'Content-Type': 'foo/bar', 'X-Delete-After': '60'}) self.app.update_request(req) @@ -4465,7 +4546,7 @@ class TestObjectController(unittest.TestCase): 'object') set_http_connect(200, 200, 202, 202, 202) self.app.memcache.store = {} - req = Request.blank('/a/c/o', {}, + req = Request.blank('/v1/a/c/o', {}, headers={'Content-Type': 'foo/bar', 'X-Delete-After': '60'}) self.app.update_request(req) @@ -4483,7 +4564,7 @@ class TestObjectController(unittest.TestCase): 'container', 'object') set_http_connect(200, 200, 200, 200, 200, 202, 202, 202) self.app.memcache.store = {} - req = Request.blank('/a/c/o', {}, + req = Request.blank('/v1/a/c/o', {}, headers={'Content-Type': 'foo/bar', 'X-Delete-After': '60.1'}) self.app.update_request(req) @@ -4498,7 +4579,7 @@ class TestObjectController(unittest.TestCase): 'container', 'object') set_http_connect(200, 200, 200, 200, 200, 202, 202, 202) self.app.memcache.store = {} - req = Request.blank('/a/c/o', {}, + req = Request.blank('/v1/a/c/o', {}, headers={'Content-Type': 'foo/bar', 'X-Delete-After': '-60'}) self.app.update_request(req) @@ -4522,7 +4603,7 @@ class TestObjectController(unittest.TestCase): set_http_connect(200, 200) self.app.memcache.store = {} t = str(int(time.time() + 100)) - req = Request.blank('/a/c/o', {}, + req = Request.blank('/v1/a/c/o', {}, headers={'Content-Type': 'foo/bar', 'X-Delete-At': t}) self.app.update_request(req) @@ -4534,7 +4615,7 @@ class TestObjectController(unittest.TestCase): self.assertTrue('X-Delete-At-Container' in given_headers) t = str(int(time.time() + 100)) + '.1' - req = Request.blank('/a/c/o', {}, + req = Request.blank('/v1/a/c/o', {}, headers={'Content-Type': 'foo/bar', 'X-Delete-At': t}) self.app.update_request(req) @@ -4543,7 +4624,7 @@ class TestObjectController(unittest.TestCase): self.assertTrue('Non-integer X-Delete-At' in resp.body) t = str(int(time.time() - 100)) - req = Request.blank('/a/c/o', {}, + req = Request.blank('/v1/a/c/o', {}, headers={'Content-Type': 'foo/bar', 'X-Delete-At': t}) self.app.update_request(req) @@ -4562,7 +4643,7 @@ class TestObjectController(unittest.TestCase): try: t = time.time() time.time = lambda: t - req = Request.blank('/a/c/o', {}, + req = Request.blank('/v1/a/c/o', {}, headers={'Content-Length': '0', 'Content-Type': 'foo/bar', 'X-Delete-After': '60'}) @@ -4581,7 +4662,7 @@ class TestObjectController(unittest.TestCase): 'container', 'object') set_http_connect(200, 200, 201, 201, 201) self.app.memcache.store = {} - req = Request.blank('/a/c/o', {}, + req = Request.blank('/v1/a/c/o', {}, headers={'Content-Length': '0', 'Content-Type': 'foo/bar', 'X-Delete-After': '60.1'}) @@ -4597,7 +4678,7 @@ class TestObjectController(unittest.TestCase): 'container', 'object') set_http_connect(200, 200, 201, 201, 201) self.app.memcache.store = {} - req = Request.blank('/a/c/o', {}, + req = Request.blank('/v1/a/c/o', {}, headers={'Content-Length': '0', 'Content-Type': 'foo/bar', 'X-Delete-After': '-60'}) @@ -4621,7 +4702,7 @@ class TestObjectController(unittest.TestCase): set_http_connect(200, 200) self.app.memcache.store = {} t = str(int(time.time() + 100)) - req = Request.blank('/a/c/o', {}, + req = Request.blank('/v1/a/c/o', {}, headers={'Content-Length': '0', 'Content-Type': 'foo/bar', 'X-Delete-At': t}) @@ -4634,7 +4715,7 @@ class TestObjectController(unittest.TestCase): self.assertTrue('X-Delete-At-Container' in given_headers) t = str(int(time.time() + 100)) + '.1' - req = Request.blank('/a/c/o', {}, + req = Request.blank('/v1/a/c/o', {}, headers={'Content-Length': '0', 'Content-Type': 'foo/bar', 'X-Delete-At': t}) @@ -4644,7 +4725,7 @@ class TestObjectController(unittest.TestCase): self.assertTrue('Non-integer X-Delete-At' in resp.body) t = str(int(time.time() - 100)) - req = Request.blank('/a/c/o', {}, + req = Request.blank('/v1/a/c/o', {}, headers={'Content-Length': '0', 'Content-Type': 'foo/bar', 'X-Delete-At': t}) @@ -4674,7 +4755,10 @@ class TestObjectController(unittest.TestCase): # Remember Request instance count, make sure the GC is run for pythons # without reference counting. for i in xrange(4): + sleep(0) # let eventlet do its thing gc.collect() + else: + sleep(0) before_request_instances = len(_request_instances) # GET test file, but disconnect early sock = connect_tcp(('localhost', prolis.getsockname()[1])) @@ -4691,10 +4775,12 @@ class TestObjectController(unittest.TestCase): fd.read(1) fd.close() sock.close() - sleep(0) # let eventlet do it's thing # Make sure the GC is run again for pythons without reference counting for i in xrange(4): + sleep(0) # let eventlet do its thing gc.collect() + else: + sleep(0) self.assertEquals(before_request_instances, len(_request_instances)) def test_OPTIONS(self): @@ -4706,7 +4792,7 @@ class TestObjectController(unittest.TestCase): return {} controller.container_info = my_empty_container_info req = Request.blank( - '/a/c/o.jpg', + '/v1/a/c/o.jpg', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'http://foo.com', 'Access-Control-Request-Method': 'GET'}) @@ -4717,7 +4803,7 @@ class TestObjectController(unittest.TestCase): return {'cors': {'allow_origin': None}} controller.container_info = my_empty_origin_container_info req = Request.blank( - '/a/c/o.jpg', + '/v1/a/c/o.jpg', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'http://foo.com', 'Access-Control-Request-Method': 'GET'}) @@ -4733,7 +4819,7 @@ class TestObjectController(unittest.TestCase): } controller.container_info = my_container_info req = Request.blank( - '/a/c/o.jpg', + '/v1/a/c/o.jpg', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'https://foo.bar', 'Access-Control-Request-Method': 'GET'}) @@ -4751,13 +4837,13 @@ class TestObjectController(unittest.TestCase): 7) self.assertEquals('999', resp.headers['access-control-max-age']) req = Request.blank( - '/a/c/o.jpg', + '/v1/a/c/o.jpg', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'https://foo.bar'}) req.content_length = 0 resp = controller.OPTIONS(req) self.assertEquals(401, resp.status_int) - req = Request.blank('/a/c/o.jpg', {'REQUEST_METHOD': 'OPTIONS'}) + req = Request.blank('/v1/a/c/o.jpg', {'REQUEST_METHOD': 'OPTIONS'}) req.content_length = 0 resp = controller.OPTIONS(req) self.assertEquals(200, resp.status_int) @@ -4766,13 +4852,13 @@ class TestObjectController(unittest.TestCase): verb in resp.headers['Allow']) self.assertEquals(len(resp.headers['Allow'].split(', ')), 7) req = Request.blank( - '/a/c/o.jpg', + '/v1/a/c/o.jpg', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'http://foo.com'}) resp = controller.OPTIONS(req) self.assertEquals(401, resp.status_int) req = Request.blank( - '/a/c/o.jpg', + '/v1/a/c/o.jpg', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'http://foo.bar', 'Access-Control-Request-Method': 'GET'}) @@ -4789,7 +4875,7 @@ class TestObjectController(unittest.TestCase): } controller.container_info = my_container_info_wildcard req = Request.blank( - '/a/c/o.jpg', + '/v1/a/c/o.jpg', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'https://bar.baz', 'Access-Control-Request-Method': 'GET'}) @@ -4826,7 +4912,7 @@ class TestObjectController(unittest.TestCase): }) req = Request.blank( - '/a/c/o.jpg', + '/v1/a/c/o.jpg', {'REQUEST_METHOD': 'GET'}, headers={'Origin': 'http://foo.bar'}) @@ -4876,7 +4962,7 @@ class TestObjectController(unittest.TestCase): key=lambda d: d.get(header_list[0]) or 'z') def test_PUT_x_container_headers_with_equal_replicas(self): - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '5'}, body='12345') controller = proxy_server.ObjectController(self.app, 'a', 'c', 'o') seen_headers = self._gather_x_container_headers( @@ -4897,7 +4983,7 @@ class TestObjectController(unittest.TestCase): def test_PUT_x_container_headers_with_fewer_container_replicas(self): self.app.container_ring.set_replicas(2) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '5'}, body='12345') controller = proxy_server.ObjectController(self.app, 'a', 'c', 'o') seen_headers = self._gather_x_container_headers( @@ -4919,7 +5005,7 @@ class TestObjectController(unittest.TestCase): def test_PUT_x_container_headers_with_more_container_replicas(self): self.app.container_ring.set_replicas(4) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Length': '5'}, body='12345') controller = proxy_server.ObjectController(self.app, 'a', 'c', 'o') seen_headers = self._gather_x_container_headers( @@ -4942,7 +5028,8 @@ class TestObjectController(unittest.TestCase): self.app.container_ring.set_replicas(4) self.app.object_post_as_copy = False - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'POST'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'POST'}, headers={'Content-Type': 'application/stuff'}) controller = proxy_server.ObjectController(self.app, 'a', 'c', 'o') seen_headers = self._gather_x_container_headers( @@ -4964,7 +5051,8 @@ class TestObjectController(unittest.TestCase): def test_DELETE_x_container_headers_with_more_container_replicas(self): self.app.container_ring.set_replicas(4) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'DELETE'}, + req = Request.blank('/v1/a/c/o', + environ={'REQUEST_METHOD': 'DELETE'}, headers={'Content-Type': 'application/stuff'}) controller = proxy_server.ObjectController(self.app, 'a', 'c', 'o') seen_headers = self._gather_x_container_headers( @@ -4993,7 +5081,7 @@ class TestObjectController(unittest.TestCase): delete_at_timestamp / self.app.expiring_objects_container_divisor * self.app.expiring_objects_container_divisor) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Type': 'application/stuff', 'Content-Length': '0', 'X-Delete-At': str(delete_at_timestamp)}) @@ -5031,7 +5119,7 @@ class TestObjectController(unittest.TestCase): delete_at_timestamp / self.app.expiring_objects_container_divisor * self.app.expiring_objects_container_divisor) - req = Request.blank('/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c/o', environ={'REQUEST_METHOD': 'PUT'}, headers={'Content-Type': 'application/stuff', 'Content-Length': 0, 'X-Delete-At': str(delete_at_timestamp)}) @@ -5086,14 +5174,14 @@ class TestContainerController(unittest.TestCase): kwargs['missing_container'] = missing_container set_http_connect(*statuses, **kwargs) self.app.memcache.store = {} - req = Request.blank('/a/c', headers={'Content-Length': '0', + req = Request.blank('/v1/a/c', headers={'Content-Length': '0', 'Content-Type': 'text/plain'}) self.app.update_request(req) res = method(req) self.assertEquals(res.status_int, expected) set_http_connect(*statuses, **kwargs) self.app.memcache.store = {} - req = Request.blank('/a/c/', headers={'Content-Length': '0', + req = Request.blank('/v1/a/c/', headers={'Content-Length': '0', 'Content-Type': 'text/plain'}) self.app.update_request(req) res = method(req) @@ -5107,7 +5195,7 @@ class TestContainerController(unittest.TestCase): c_expected=None, a_expected=None, **kwargs): set_http_connect(*statuses, **kwargs) self.app.memcache.store = {} - req = Request.blank('/a/c', {}) + req = Request.blank('/v1/a/c', {}) self.app.update_request(req) res = controller.HEAD(req) self.assertEquals(res.status[:len(str(expected))], @@ -5131,7 +5219,7 @@ class TestContainerController(unittest.TestCase): set_http_connect(*statuses, **kwargs) self.app.memcache.store = {} - req = Request.blank('/a/c', {}) + req = Request.blank('/v1/a/c', {}) self.app.update_request(req) res = controller.GET(req) self.assertEquals(res.status[:len(str(expected))], @@ -5181,7 +5269,7 @@ class TestContainerController(unittest.TestCase): def test_status_map(statuses, expected, **kwargs): set_http_connect(*statuses, **kwargs) self.app.memcache.store = {} - req = Request.blank('/a/c', {}) + req = Request.blank('/v1/a/c', {}) req.content_length = 0 self.app.update_request(req) res = controller.PUT(req) @@ -5239,7 +5327,7 @@ class TestContainerController(unittest.TestCase): def test_status_map(statuses, expected, **kwargs): set_http_connect(*statuses, **kwargs) self.app.memcache.store = {} - req = Request.blank('/a/c', {}) + req = Request.blank('/v1/a/c', {}) req.content_length = 0 self.app.update_request(req) res = controller.POST(req) @@ -5318,26 +5406,30 @@ class TestContainerController(unittest.TestCase): else: set_http_connect(200, 200, 200, 200) self.app.memcache.store = {} - req = Request.blank('/a/c', environ={'REQUEST_METHOD': meth}) + req = Request.blank('/v1/a/c', + environ={'REQUEST_METHOD': meth}) self.app.update_request(req) resp = getattr(controller, meth)(req) self.assertEquals(resp.status_int, 200) set_http_connect(404, 404, 404, 200, 200, 200) # Make sure it is a blank request wthout env caching - req = Request.blank('/a/c', environ={'REQUEST_METHOD': meth}) + req = Request.blank('/v1/a/c', + environ={'REQUEST_METHOD': meth}) resp = getattr(controller, meth)(req) self.assertEquals(resp.status_int, 404) set_http_connect(503, 404, 404) # Make sure it is a blank request wthout env caching - req = Request.blank('/a/c', environ={'REQUEST_METHOD': meth}) + req = Request.blank('/v1/a/c', + environ={'REQUEST_METHOD': meth}) resp = getattr(controller, meth)(req) self.assertEquals(resp.status_int, 404) set_http_connect(503, 404, raise_exc=True) # Make sure it is a blank request wthout env caching - req = Request.blank('/a/c', environ={'REQUEST_METHOD': meth}) + req = Request.blank('/v1/a/c', + environ={'REQUEST_METHOD': meth}) resp = getattr(controller, meth)(req) self.assertEquals(resp.status_int, 404) @@ -5346,7 +5438,8 @@ class TestContainerController(unittest.TestCase): dev['last_error'] = time.time() set_http_connect(200, 200, 200, 200, 200, 200) # Make sure it is a blank request wthout env caching - req = Request.blank('/a/c', environ={'REQUEST_METHOD': meth}) + req = Request.blank('/v1/a/c', + environ={'REQUEST_METHOD': meth}) resp = getattr(controller, meth)(req) self.assertEquals(resp.status_int, 404) @@ -5371,7 +5464,7 @@ class TestContainerController(unittest.TestCase): self.app.memcache = MockMemcache(allow_lock=True) set_http_connect(200, 201, 201, 201, missing_container=True) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': 'PUT'}) + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': 'PUT'}) self.app.update_request(req) res = controller.PUT(req) self.assertEquals(res.status_int, 201) @@ -5429,7 +5522,7 @@ class TestContainerController(unittest.TestCase): set_http_connect(200, 200, body='{}') controller = proxy_server.ContainerController(self.app, 'account', 'container') - req = Request.blank('/a/c?format=json') + req = Request.blank('/v1/a/c?format=json') self.app.update_request(req) res = controller.GET(req) self.assert_('accept-ranges' in res.headers) @@ -5440,7 +5533,7 @@ class TestContainerController(unittest.TestCase): set_http_connect(200, 200, body='{}') controller = proxy_server.ContainerController(self.app, 'account', 'container') - req = Request.blank('/a/c?format=json') + req = Request.blank('/v1/a/c?format=json') self.app.update_request(req) res = controller.HEAD(req) self.assert_('accept-ranges' in res.headers) @@ -5483,7 +5576,8 @@ class TestContainerController(unittest.TestCase): controller = \ proxy_server.ContainerController(self.app, 'a', 'c') set_http_connect(200, 201, 201, 201, give_connect=test_connect) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', + environ={'REQUEST_METHOD': method}, headers={test_header: test_value}) self.app.update_request(req) getattr(controller, method)(req) @@ -5499,20 +5593,20 @@ class TestContainerController(unittest.TestCase): with save_globals(): controller = proxy_server.ContainerController(self.app, 'a', 'c') set_http_connect(200, 201, 201, 201) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}) + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}) self.app.update_request(req) resp = getattr(controller, method)(req) self.assertEquals(resp.status_int, 201) set_http_connect(201, 201, 201) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers={'X-Container-Meta-' + ('a' * MAX_META_NAME_LENGTH): 'v'}) self.app.update_request(req) resp = getattr(controller, method)(req) self.assertEquals(resp.status_int, 201) set_http_connect(201, 201, 201) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers={'X-Container-Meta-' + ('a' * (MAX_META_NAME_LENGTH + 1)): 'v'}) self.app.update_request(req) @@ -5520,14 +5614,14 @@ class TestContainerController(unittest.TestCase): self.assertEquals(resp.status_int, 400) set_http_connect(201, 201, 201) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers={'X-Container-Meta-Too-Long': 'a' * MAX_META_VALUE_LENGTH}) self.app.update_request(req) resp = getattr(controller, method)(req) self.assertEquals(resp.status_int, 201) set_http_connect(201, 201, 201) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers={'X-Container-Meta-Too-Long': 'a' * (MAX_META_VALUE_LENGTH + 1)}) self.app.update_request(req) @@ -5538,7 +5632,7 @@ class TestContainerController(unittest.TestCase): headers = {} for x in xrange(MAX_META_COUNT): headers['X-Container-Meta-%d' % x] = 'v' - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers=headers) self.app.update_request(req) resp = getattr(controller, method)(req) @@ -5547,7 +5641,7 @@ class TestContainerController(unittest.TestCase): headers = {} for x in xrange(MAX_META_COUNT + 1): headers['X-Container-Meta-%d' % x] = 'v' - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers=headers) self.app.update_request(req) resp = getattr(controller, method)(req) @@ -5565,7 +5659,7 @@ class TestContainerController(unittest.TestCase): if MAX_META_OVERALL_SIZE - size > 1: headers['X-Container-Meta-a'] = \ 'a' * (MAX_META_OVERALL_SIZE - size - 1) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers=headers) self.app.update_request(req) resp = getattr(controller, method)(req) @@ -5573,7 +5667,7 @@ class TestContainerController(unittest.TestCase): set_http_connect(201, 201, 201) headers['X-Container-Meta-a'] = \ 'a' * (MAX_META_OVERALL_SIZE - size) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers=headers) self.app.update_request(req) resp = getattr(controller, method)(req) @@ -5589,7 +5683,7 @@ class TestContainerController(unittest.TestCase): set_http_connect(200, 201, 201, 201) controller = proxy_server.ContainerController(self.app, 'account', 'container') - req = Request.blank('/a/c', environ={'REQUEST_METHOD': 'POST'}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': 'POST'}, headers={'X-Container-Read': '.r:*'}) req.environ['swift.clean_acl'] = clean_acl self.app.update_request(req) @@ -5600,7 +5694,7 @@ class TestContainerController(unittest.TestCase): set_http_connect(200, 201, 201, 201) controller = proxy_server.ContainerController(self.app, 'account', 'container') - req = Request.blank('/a/c', environ={'REQUEST_METHOD': 'POST'}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': 'POST'}, headers={'X-Container-Write': '.r:*'}) req.environ['swift.clean_acl'] = clean_acl self.app.update_request(req) @@ -5617,7 +5711,7 @@ class TestContainerController(unittest.TestCase): set_http_connect(200, 201, 201, 201) controller = proxy_server.ContainerController(self.app, 'account', 'container') - req = Request.blank('/a/c', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': 'PUT'}, headers={'X-Container-Read': '.r:*'}) req.environ['swift.clean_acl'] = clean_acl self.app.update_request(req) @@ -5628,7 +5722,7 @@ class TestContainerController(unittest.TestCase): set_http_connect(200, 201, 201, 201) controller = proxy_server.ContainerController(self.app, 'account', 'container') - req = Request.blank('/a/c', environ={'REQUEST_METHOD': 'PUT'}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': 'PUT'}, headers={'X-Container-Write': '.r:*'}) req.environ['swift.clean_acl'] = clean_acl self.app.update_request(req) @@ -5640,9 +5734,10 @@ class TestContainerController(unittest.TestCase): set_http_connect(200, 204, 204, 204) controller = proxy_server.ContainerController(self.app, 'account', 'container') - req = Request.blank('/a/c') + req = Request.blank('/v1/a/c') self.app.update_request(req) res = controller.GET(req) + self.assertEquals(res.status_int, 204) self.assertEquals( res.environ['swift.container/a/c']['status'], 204) self.assertEquals(res.content_length, 0) @@ -5658,7 +5753,7 @@ class TestContainerController(unittest.TestCase): set_http_connect(200, 201, 201, 201) controller = proxy_server.ContainerController(self.app, 'account', 'container') - req = Request.blank('/a/c') + req = Request.blank('/v1/a/c') req.environ['swift.authorize'] = authorize self.app.update_request(req) res = controller.GET(req) @@ -5675,7 +5770,7 @@ class TestContainerController(unittest.TestCase): set_http_connect(200, 201, 201, 201) controller = proxy_server.ContainerController(self.app, 'account', 'container') - req = Request.blank('/a/c', {'REQUEST_METHOD': 'HEAD'}) + req = Request.blank('/v1/a/c', {'REQUEST_METHOD': 'HEAD'}) req.environ['swift.authorize'] = authorize self.app.update_request(req) controller.HEAD(req) @@ -5689,7 +5784,7 @@ class TestContainerController(unittest.TestCase): return {} controller.container_info = my_empty_container_info req = Request.blank( - '/a/c', + '/v1/a/c', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'http://foo.com', 'Access-Control-Request-Method': 'GET'}) @@ -5700,7 +5795,7 @@ class TestContainerController(unittest.TestCase): return {'cors': {'allow_origin': None}} controller.container_info = my_empty_origin_container_info req = Request.blank( - '/a/c', + '/v1/a/c', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'http://foo.com', 'Access-Control-Request-Method': 'GET'}) @@ -5716,7 +5811,7 @@ class TestContainerController(unittest.TestCase): } controller.container_info = my_container_info req = Request.blank( - '/a/c', + '/v1/a/c', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'https://foo.bar', 'Access-Control-Request-Method': 'GET'}) @@ -5734,13 +5829,13 @@ class TestContainerController(unittest.TestCase): 6) self.assertEquals('999', resp.headers['access-control-max-age']) req = Request.blank( - '/a/c', + '/v1/a/c', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'https://foo.bar'}) req.content_length = 0 resp = controller.OPTIONS(req) self.assertEquals(401, resp.status_int) - req = Request.blank('/a/c', {'REQUEST_METHOD': 'OPTIONS'}) + req = Request.blank('/v1/a/c', {'REQUEST_METHOD': 'OPTIONS'}) req.content_length = 0 resp = controller.OPTIONS(req) self.assertEquals(200, resp.status_int) @@ -5749,14 +5844,14 @@ class TestContainerController(unittest.TestCase): verb in resp.headers['Allow']) self.assertEquals(len(resp.headers['Allow'].split(', ')), 6) req = Request.blank( - '/a/c', + '/v1/a/c', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'http://foo.bar', 'Access-Control-Request-Method': 'GET'}) resp = controller.OPTIONS(req) self.assertEquals(401, resp.status_int) req = Request.blank( - '/a/c', + '/v1/a/c', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'http://foo.bar', 'Access-Control-Request-Method': 'GET'}) @@ -5773,7 +5868,7 @@ class TestContainerController(unittest.TestCase): } controller.container_info = my_container_info_wildcard req = Request.blank( - '/a/c/o.jpg', + '/v1/a/c/o.jpg', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'https://bar.baz', 'Access-Control-Request-Method': 'GET'}) @@ -5792,7 +5887,7 @@ class TestContainerController(unittest.TestCase): self.assertEquals('999', resp.headers['access-control-max-age']) req = Request.blank( - '/a/c/o.jpg', + '/v1/a/c/o.jpg', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'https://bar.baz', 'Access-Control-Request-Headers': @@ -5825,7 +5920,7 @@ class TestContainerController(unittest.TestCase): }) req = Request.blank( - '/a/c', + '/v1/a/c', {'REQUEST_METHOD': 'GET'}, headers={'Origin': 'http://foo.bar'}) @@ -5875,7 +5970,7 @@ class TestContainerController(unittest.TestCase): def test_PUT_x_account_headers_with_fewer_account_replicas(self): self.app.account_ring.set_replicas(2) - req = Request.blank('/a/c', headers={'': ''}) + req = Request.blank('/v1/a/c', headers={'': ''}) controller = proxy_server.ContainerController(self.app, 'a', 'c') seen_headers = self._gather_x_account_headers( @@ -5895,7 +5990,7 @@ class TestContainerController(unittest.TestCase): def test_PUT_x_account_headers_with_more_account_replicas(self): self.app.account_ring.set_replicas(4) - req = Request.blank('/a/c', headers={'': ''}) + req = Request.blank('/v1/a/c', headers={'': ''}) controller = proxy_server.ContainerController(self.app, 'a', 'c') seen_headers = self._gather_x_account_headers( @@ -5915,7 +6010,7 @@ class TestContainerController(unittest.TestCase): def test_DELETE_x_account_headers_with_fewer_account_replicas(self): self.app.account_ring.set_replicas(2) - req = Request.blank('/a/c', headers={'': ''}) + req = Request.blank('/v1/a/c', headers={'': ''}) controller = proxy_server.ContainerController(self.app, 'a', 'c') seen_headers = self._gather_x_account_headers( @@ -5935,7 +6030,7 @@ class TestContainerController(unittest.TestCase): def test_DELETE_x_account_headers_with_more_account_replicas(self): self.app.account_ring.set_replicas(4) - req = Request.blank('/a/c', headers={'': ''}) + req = Request.blank('/v1/a/c', headers={'': ''}) controller = proxy_server.ContainerController(self.app, 'a', 'c') seen_headers = self._gather_x_account_headers( @@ -5953,6 +6048,19 @@ class TestContainerController(unittest.TestCase): 'X-Account-Device': 'sdc'} ]) + def test_node_read_timeout_retry_to_container(self): + with save_globals(): + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': 'GET'}) + self.app.node_timeout = 0.1 + set_http_connect(200, 200, 200, body='abcdef', slow=[2]) + resp = req.get_response(self.app) + got_exc = False + try: + resp.body + except ChunkReadTimeout: + got_exc = True + self.assert_(got_exc) + class TestAccountController(unittest.TestCase): @@ -5965,7 +6073,7 @@ class TestAccountController(unittest.TestCase): def assert_status_map(self, method, statuses, expected, env_expected=None): with save_globals(): set_http_connect(*statuses) - req = Request.blank('/a', {}) + req = Request.blank('/v1/a', {}) self.app.update_request(req) res = method(req) self.assertEquals(res.status_int, expected) @@ -5973,7 +6081,7 @@ class TestAccountController(unittest.TestCase): self.assertEquals(res.environ['swift.account/a']['status'], env_expected) set_http_connect(*statuses) - req = Request.blank('/a/', {}) + req = Request.blank('/v1/a/', {}) self.app.update_request(req) res = method(req) self.assertEquals(res.status_int, expected) @@ -5985,7 +6093,7 @@ class TestAccountController(unittest.TestCase): with save_globals(): self.app.allow_account_management = False controller = proxy_server.AccountController(self.app, 'account') - req = Request.blank('/account', {'REQUEST_METHOD': 'OPTIONS'}) + req = Request.blank('/v1/account', {'REQUEST_METHOD': 'OPTIONS'}) req.content_length = 0 resp = controller.OPTIONS(req) self.assertEquals(200, resp.status_int) @@ -5999,7 +6107,7 @@ class TestAccountController(unittest.TestCase): self.app.allow_account_management = False controller = proxy_server.AccountController(self.app, 'account') req = Request.blank( - '/account', {'REQUEST_METHOD': 'OPTIONS'}, + '/v1/account', {'REQUEST_METHOD': 'OPTIONS'}, headers={'Origin': 'http://foo.com', 'Access-Control-Request-Method': 'GET'}) req.content_length = 0 @@ -6012,7 +6120,7 @@ class TestAccountController(unittest.TestCase): self.app.allow_account_management = True controller = proxy_server.AccountController(self.app, 'account') - req = Request.blank('/account', {'REQUEST_METHOD': 'OPTIONS'}) + req = Request.blank('/v1/account', {'REQUEST_METHOD': 'OPTIONS'}) req.content_length = 0 resp = controller.OPTIONS(req) self.assertEquals(200, resp.status_int) @@ -6130,7 +6238,7 @@ class TestAccountController(unittest.TestCase): dev['ip'] = '127.0.0.1' dev['port'] = 1 # can't connect on this port controller = proxy_server.AccountController(self.app, 'account') - req = Request.blank('/account', environ={'REQUEST_METHOD': 'HEAD'}) + req = Request.blank('/v1/account', environ={'REQUEST_METHOD': 'HEAD'}) self.app.update_request(req) resp = controller.HEAD(req) self.assertEquals(resp.status_int, 503) @@ -6141,7 +6249,7 @@ class TestAccountController(unittest.TestCase): dev['ip'] = '127.0.0.1' dev['port'] = -1 # invalid port number controller = proxy_server.AccountController(self.app, 'account') - req = Request.blank('/account', environ={'REQUEST_METHOD': 'HEAD'}) + req = Request.blank('/v1/account', environ={'REQUEST_METHOD': 'HEAD'}) self.app.update_request(req) resp = controller.HEAD(req) self.assertEquals(resp.status_int, 503) @@ -6150,7 +6258,7 @@ class TestAccountController(unittest.TestCase): with save_globals(): set_http_connect(200, 200, body='{}') controller = proxy_server.AccountController(self.app, 'account') - req = Request.blank('/a?format=json') + req = Request.blank('/v1/a?format=json') self.app.update_request(req) res = controller.GET(req) self.assert_('accept-ranges' in res.headers) @@ -6160,7 +6268,7 @@ class TestAccountController(unittest.TestCase): with save_globals(): set_http_connect(200, 200, body='{}') controller = proxy_server.AccountController(self.app, 'account') - req = Request.blank('/a?format=json') + req = Request.blank('/v1/a?format=json') self.app.update_request(req) res = controller.HEAD(req) res.body @@ -6174,7 +6282,7 @@ class TestAccountController(unittest.TestCase): def test_status_map(statuses, expected, **kwargs): set_http_connect(*statuses, **kwargs) self.app.memcache.store = {} - req = Request.blank('/a', {}) + req = Request.blank('/v1/a', {}) req.content_length = 0 self.app.update_request(req) res = controller.PUT(req) @@ -6239,7 +6347,8 @@ class TestAccountController(unittest.TestCase): controller = \ proxy_server.AccountController(self.app, 'a') set_http_connect(201, 201, 201, give_connect=test_connect) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', + environ={'REQUEST_METHOD': method}, headers={test_header: test_value}) self.app.update_request(req) getattr(controller, method)(req) @@ -6256,20 +6365,20 @@ class TestAccountController(unittest.TestCase): self.app.allow_account_management = True controller = proxy_server.AccountController(self.app, 'a') set_http_connect(200, 201, 201, 201) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}) + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}) self.app.update_request(req) resp = getattr(controller, method)(req) self.assertEquals(resp.status_int, 201) set_http_connect(201, 201, 201) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers={'X-Account-Meta-' + ('a' * MAX_META_NAME_LENGTH): 'v'}) self.app.update_request(req) resp = getattr(controller, method)(req) self.assertEquals(resp.status_int, 201) set_http_connect(201, 201, 201) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers={'X-Account-Meta-' + ('a' * (MAX_META_NAME_LENGTH + 1)): 'v'}) self.app.update_request(req) @@ -6277,14 +6386,14 @@ class TestAccountController(unittest.TestCase): self.assertEquals(resp.status_int, 400) set_http_connect(201, 201, 201) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers={'X-Account-Meta-Too-Long': 'a' * MAX_META_VALUE_LENGTH}) self.app.update_request(req) resp = getattr(controller, method)(req) self.assertEquals(resp.status_int, 201) set_http_connect(201, 201, 201) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers={'X-Account-Meta-Too-Long': 'a' * (MAX_META_VALUE_LENGTH + 1)}) self.app.update_request(req) @@ -6295,7 +6404,7 @@ class TestAccountController(unittest.TestCase): headers = {} for x in xrange(MAX_META_COUNT): headers['X-Account-Meta-%d' % x] = 'v' - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers=headers) self.app.update_request(req) resp = getattr(controller, method)(req) @@ -6304,7 +6413,7 @@ class TestAccountController(unittest.TestCase): headers = {} for x in xrange(MAX_META_COUNT + 1): headers['X-Account-Meta-%d' % x] = 'v' - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers=headers) self.app.update_request(req) resp = getattr(controller, method)(req) @@ -6322,7 +6431,7 @@ class TestAccountController(unittest.TestCase): if MAX_META_OVERALL_SIZE - size > 1: headers['X-Account-Meta-a'] = \ 'a' * (MAX_META_OVERALL_SIZE - size - 1) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers=headers) self.app.update_request(req) resp = getattr(controller, method)(req) @@ -6330,7 +6439,7 @@ class TestAccountController(unittest.TestCase): set_http_connect(201, 201, 201) headers['X-Account-Meta-a'] = \ 'a' * (MAX_META_OVERALL_SIZE - size) - req = Request.blank('/a/c', environ={'REQUEST_METHOD': method}, + req = Request.blank('/v1/a/c', environ={'REQUEST_METHOD': method}, headers=headers) self.app.update_request(req) resp = getattr(controller, method)(req) @@ -6343,7 +6452,7 @@ class TestAccountController(unittest.TestCase): def test_status_map(statuses, expected, **kwargs): set_http_connect(*statuses, **kwargs) self.app.memcache.store = {} - req = Request.blank('/a', {'REQUEST_METHOD': 'DELETE'}) + req = Request.blank('/v1/a', {'REQUEST_METHOD': 'DELETE'}) req.content_length = 0 self.app.update_request(req) res = controller.DELETE(req) @@ -6366,7 +6475,8 @@ class TestAccountController(unittest.TestCase): def test_status_map(statuses, expected, **kwargs): set_http_connect(*statuses, **kwargs) self.app.memcache.store = {} - req = Request.blank('/a?whoops', {'REQUEST_METHOD': 'DELETE'}) + req = Request.blank('/v1/a?whoops', + environ={'REQUEST_METHOD': 'DELETE'}) req.content_length = 0 self.app.update_request(req) res = controller.DELETE(req) @@ -6856,7 +6966,7 @@ class TestProxyObjectPerformance(unittest.TestCase): self.obj_len = obj_len def test_GET_debug_large_file(self): - for i in range(0, 10): + for i in range(10): start = time.time() prolis = _test_sockets[0] @@ -6885,6 +6995,33 @@ class TestProxyObjectPerformance(unittest.TestCase): print "Run %02d took %07.03f" % (i, end - start) +class TestSwiftInfo(unittest.TestCase): + def setUp(self): + utils._swift_info = {} + utils._swift_admin_info = {} + + def test_registered_defaults(self): + proxy_server.Application({}, FakeMemcache(), + account_ring=FakeRing(), + container_ring=FakeRing(), + object_ring=FakeRing) + + si = utils.get_swift_info()['swift'] + self.assertTrue('version' in si) + self.assertEqual(si['max_file_size'], MAX_FILE_SIZE) + self.assertEqual(si['max_meta_name_length'], MAX_META_NAME_LENGTH) + self.assertEqual(si['max_meta_value_length'], MAX_META_VALUE_LENGTH) + self.assertEqual(si['max_meta_count'], MAX_META_COUNT) + self.assertEqual(si['account_listing_limit'], ACCOUNT_LISTING_LIMIT) + self.assertEqual(si['container_listing_limit'], + CONTAINER_LISTING_LIMIT) + self.assertEqual(si['max_account_name_length'], + MAX_ACCOUNT_NAME_LENGTH) + self.assertEqual(si['max_container_name_length'], + MAX_CONTAINER_NAME_LENGTH) + self.assertEqual(si['max_object_name_length'], MAX_OBJECT_NAME_LENGTH) + + if __name__ == '__main__': setup() try: diff --git a/tools/requirements.txt b/tools/requirements.txt new file mode 100644 index 0000000..1139866 --- /dev/null +++ b/tools/requirements.txt @@ -0,0 +1,8 @@ +dnspython>=1.9.4 +eventlet>=0.9.15 +greenlet>=0.3.1 +netifaces>=0.5 +pastedeploy>=1.3.3 +simplejson>=2.0.9 +xattr>=0.4 +python-swiftclient diff --git a/tools/test-requires b/tools/test-requires index 6bf711e..d2c027f 100644 --- a/tools/test-requires +++ b/tools/test-requires @@ -8,7 +8,7 @@ nose nosexcover openstack.nose_plugin nosehtmloutput -sphinx>=1.1.2 +sphinx>=1.1.2,<1.2 mock>=0.8.0 python-keystoneclient prettytable diff --git a/tox.ini b/tox.ini index acb6065..07f0587 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,11 @@ [tox] envlist = py26,py27,pep8,functest,ksfunctest +minversion = 1.6 +skipsdist = True [testenv] +usedevelop = True +install_command = pip install --allow-external netifaces --allow-insecure netifaces -U {opts} {packages} whitelist_externals=bash setenv = VIRTUAL_ENV={envdir} NOSE_WITH_OPENSTACK=1 @@ -11,9 +15,10 @@ setenv = VIRTUAL_ENV={envdir} NOSE_OPENSTACK_SHOW_ELAPSED=1 NOSE_OPENSTACK_STDOUT=1 deps = - https://launchpad.net/gluster-swift/icehouse/1.10.2/+download/swift-1.10.0.172.g9fe7748.tar.gz + https://launchpad.net/gluster-swift/icehouse/1.11.0/+download/swift-1.11.0.71.gf310006.tar.gz --download-cache={homedir}/.pipcache -r{toxinidir}/tools/test-requires + -r{toxinidir}/tools/requirements.txt changedir = {toxinidir}/test/unit commands = nosetests -v --exe --with-xunit --with-coverage --cover-package gluster --cover-erase --cover-xml --cover-html --cover-branches --with-html-output {posargs} -- cgit