Merge lp:~cjwatson/launchpad/upgrade-keystoneclient-swiftclient into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 18553
Proposed branch: lp:~cjwatson/launchpad/upgrade-keystoneclient-swiftclient
Merge into: lp:launchpad
Diff against target: 435 lines (+123/-43)
9 files modified
constraints.txt (+7/-5)
lib/lp/services/librarianserver/librariangc.py (+9/-5)
lib/lp/services/librarianserver/storage.py (+3/-3)
lib/lp/services/librarianserver/swift.py (+40/-7)
lib/lp/services/librarianserver/tests/test_gc.py (+2/-1)
lib/lp/services/librarianserver/tests/test_swift.py (+26/-7)
lib/lp/testing/swift/fakeswift.py (+28/-12)
lib/lp/testing/swift/tests/test_fixture.py (+4/-3)
lib/lp_sitecustomize.py (+4/-0)
To merge this branch: bzr merge lp:~cjwatson/launchpad/upgrade-keystoneclient-swiftclient
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+335391@code.launchpad.net

Commit message

Upgrade to python-keystoneclient 0.7.1 and python-swiftclient 2.0.3.

Description of the change

These were the latest versions in Icehouse, to go with keystone 2014.1.5 and
swift 1.13.1 currently on the server. Upgrading to these allows us to use a
more recent version of pbr that is compatible with other dependencies we'd
like to upgrade.

We need a few tweaks to make everything work properly:

 * quieten overly-noisy logging (needed until python-swiftclient 3.2.0);
 * explicitly restrict HashStream to the desired segment size, since
   otherwise the client will read past the end of the segment and we can end
   up with corrupted hashes;
 * advertise a keystone endpoint in the fake Swift fixture;
 * cope with slightly different exception types due to the client now using
   requests.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) wrote :

We'll probably need to tweak staging configs a bit to effectively test this. Have you verified in any depth against a non-prod Swift?

review: Approve (code)
Revision history for this message
Colin Watson (cjwatson) wrote :

OK, I eventually managed to get Icehouse Keystone and Swift deployed locally, and tested this against them. librarian-feed-swift, librariangc, downloads from the librarian after renaming aside the local files, and segmented uploads (with the threshold tweaked down to 5MiB from 5GiB) all work fine. I'm going to go ahead and land this, but let me know if you think of anything else I ought to test.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'constraints.txt'
--- constraints.txt 2017-12-22 09:59:33 +0000
+++ constraints.txt 2018-02-13 16:28:38 +0000
@@ -228,6 +228,7 @@
228auditor==0.0.3228auditor==0.0.3
229auditorclient==0.0.4229auditorclient==0.0.4
230auditorfixture==0.0.7230auditorfixture==0.0.7
231Babel==2.5.1
231backports.lzma==0.0.3232backports.lzma==0.0.3
232BeautifulSoup==3.2.1233BeautifulSoup==3.2.1
233billiard==3.3.0.20234billiard==3.3.0.20
@@ -256,7 +257,7 @@
256httplib2==0.8257httplib2==0.8
257importlib==1.0.2258importlib==1.0.2
258ipython==0.13.2259ipython==0.13.2
259iso8601==0.1.4260iso8601==0.1.12
260jsautobuild==0.2261jsautobuild==0.2
261keyring==0.6.2262keyring==0.6.2
262kombu==3.0.30263kombu==3.0.30
@@ -283,6 +284,7 @@
283meliae==0.2.0.final.0284meliae==0.2.0.final.0
284mock==1.0.1285mock==1.0.1
285mocker==1.1.1286mocker==1.1.1
287netaddr==0.7.19
286oauth==1.0288oauth==1.0
287oops==0.0.13289oops==0.0.13
288oops-amqp==0.0.8b1290oops-amqp==0.0.8b1
@@ -291,9 +293,9 @@
291oops-twisted==0.0.7293oops-twisted==0.0.7
292oops-wsgi==0.0.8294oops-wsgi==0.0.8
293ordereddict==1.1295ordereddict==1.1
294oslo.config==1.1.1296oslo.config==1.3.0
295paramiko==1.7.7.2297paramiko==1.7.7.2
296pbr==0.5.20298pbr==0.11.1
297pgbouncer==0.0.8299pgbouncer==0.0.8
298prettytable==0.7.2300prettytable==0.7.2
299psycopg2==2.6.1301psycopg2==2.6.1
@@ -306,14 +308,14 @@
306pystache==0.5.3308pystache==0.5.3
307python-dateutil==1.5309python-dateutil==1.5
308python-debian==0.1.23310python-debian==0.1.23
309python-keystoneclient==0.3.1311python-keystoneclient==0.7.1
310python-memcached==1.58312python-memcached==1.58
311python-mimeparse==0.1.4313python-mimeparse==0.1.4
312# XXX: deryck 2012-08-10314# XXX: deryck 2012-08-10
313# See lp:~deryck/python-openid/python-openid-fix1034376 which315# See lp:~deryck/python-openid/python-openid-fix1034376 which
314# reapplied a patch from wgrant to get codehosting going again.316# reapplied a patch from wgrant to get codehosting going again.
315python-openid==2.2.5-fix1034376317python-openid==2.2.5-fix1034376
316python-swiftclient==1.5.0318python-swiftclient==2.0.3
317PyYAML==3.10319PyYAML==3.10
318rabbitfixture==0.3.6320rabbitfixture==0.3.6
319requests==2.7.0321requests==2.7.0
320322
=== modified file 'lib/lp/services/librarianserver/librariangc.py'
--- lib/lp/services/librarianserver/librariangc.py 2017-04-02 01:17:50 +0000
+++ lib/lp/services/librarianserver/librariangc.py 2018-02-13 16:28:38 +0000
@@ -1,4 +1,4 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the1# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Librarian garbage collection routines"""4"""Librarian garbage collection routines"""
@@ -55,7 +55,8 @@
55 swift_connection = swift.connection_pool.get()55 swift_connection = swift.connection_pool.get()
56 container, name = swift.swift_location(content_id)56 container, name = swift.swift_location(content_id)
57 try:57 try:
58 swift_connection.head_object(container, name)58 swift.quiet_swiftclient(
59 swift_connection.head_object, container, name)
59 return True60 return True
60 except swiftclient.ClientException as x:61 except swiftclient.ClientException as x:
61 if x.http_status != 404:62 if x.http_status != 404:
@@ -79,7 +80,8 @@
79 try:80 try:
80 swift_connection = swift.connection_pool.get()81 swift_connection = swift.connection_pool.get()
81 container, name = swift.swift_location(content_id)82 container, name = swift.swift_location(content_id)
82 chunks = swift_connection.get_object(83 chunks = swift.quiet_swiftclient(
84 swift_connection.get_object,
83 container, name, resp_chunk_size=STREAM_CHUNK_SIZE)[1]85 container, name, resp_chunk_size=STREAM_CHUNK_SIZE)[1]
84 return swift.SwiftStream(swift_connection, chunks)86 return swift.SwiftStream(swift_connection, chunks)
85 except swiftclient.ClientException as x:87 except swiftclient.ClientException as x:
@@ -562,7 +564,8 @@
562 container, name = swift.swift_location(content_id)564 container, name = swift.swift_location(content_id)
563 with swift.connection() as swift_connection:565 with swift.connection() as swift_connection:
564 try:566 try:
565 swift_connection.delete_object(container, name)567 swift.quiet_swiftclient(
568 swift_connection.delete_object, container, name)
566 removed.append('Swift')569 removed.append('Swift')
567 except swiftclient.ClientException as x:570 except swiftclient.ClientException as x:
568 if x.http_status != 404:571 if x.http_status != 404:
@@ -740,7 +743,8 @@
740 container = swift.SWIFT_CONTAINER_PREFIX + str(container_num)743 container = swift.SWIFT_CONTAINER_PREFIX + str(container_num)
741 try:744 try:
742 names = sorted(745 names = sorted(
743 swift_connection.get_container(746 swift.quiet_swiftclient(
747 swift_connection.get_container,
744 container, full_listing=True)[1],748 container, full_listing=True)[1],
745 key=lambda x: map(int, x['name'].split('/')))749 key=lambda x: map(int, x['name'].split('/')))
746 for name in names:750 for name in names:
747751
=== modified file 'lib/lp/services/librarianserver/storage.py'
--- lib/lp/services/librarianserver/storage.py 2016-09-19 13:53:42 +0000
+++ lib/lp/services/librarianserver/storage.py 2018-02-13 16:28:38 +0000
@@ -1,4 +1,4 @@
1# Copyright 2009-2013 Canonical Ltd. This software is licensed under the1# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4__metaclass__ = type4__metaclass__ = type
@@ -10,9 +10,9 @@
10import tempfile10import tempfile
1111
12from swiftclient import client as swiftclient12from swiftclient import client as swiftclient
13from twisted.python import log
14from twisted.internet import defer13from twisted.internet import defer
15from twisted.internet.threads import deferToThread14from twisted.internet.threads import deferToThread
15from twisted.python import log
16from twisted.web.static import StaticProducer16from twisted.web.static import StaticProducer
1717
18from lp.registry.model.product import Product18from lp.registry.model.product import Product
@@ -124,7 +124,7 @@
124 swift_connection = swift.connection_pool.get()124 swift_connection = swift.connection_pool.get()
125 try:125 try:
126 headers, chunks = yield deferToThread(126 headers, chunks = yield deferToThread(
127 swift_connection.get_object,127 swift.quiet_swiftclient, swift_connection.get_object,
128 container, name, resp_chunk_size=self.CHUNK_SIZE)128 container, name, resp_chunk_size=self.CHUNK_SIZE)
129 swift_stream = TxSwiftStream(swift_connection, chunks)129 swift_stream = TxSwiftStream(swift_connection, chunks)
130 defer.returnValue(swift_stream)130 defer.returnValue(swift_stream)
131131
=== modified file 'lib/lp/services/librarianserver/swift.py'
--- lib/lp/services/librarianserver/swift.py 2015-02-16 00:09:14 +0000
+++ lib/lp/services/librarianserver/swift.py 2018-02-13 16:28:38 +0000
@@ -1,12 +1,17 @@
1# Copyright 2013 Canonical Ltd. This software is licensed under the1# Copyright 2013-2017 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Move files from Librarian disk storage into Swift."""4"""Move files from Librarian disk storage into Swift."""
55
6__metaclass__ = type6__metaclass__ = type
7__all__ = [7__all__ = [
8 'to_swift', 'filesystem_path', 'swift_location',8 'SWIFT_CONTAINER_PREFIX',
9 'connection', 'connection_pool', 'SWIFT_CONTAINER_PREFIX',9 'connection',
10 'connection_pool',
11 'filesystem_path',
12 'quiet_swiftclient',
13 'swift_location',
14 'to_swift',
10 ]15 ]
1116
12from contextlib import contextmanager17from contextlib import contextmanager
@@ -29,6 +34,24 @@
29ONE_DAY = 24 * 60 * 6034ONE_DAY = 24 * 60 * 60
3035
3136
37def quiet_swiftclient(func, *args, **kwargs):
38 # XXX cjwatson 2018-01-02: swiftclient has some very rude logging
39 # practices: the low-level API calls `logger.exception` when a request
40 # fails, without considering whether the caller might handle it and
41 # recover. This was introduced in 1.6.0 and removed in 3.2.0; until
42 # we're on a new enough version not to need to worry about this, we shut
43 # up the noisy logging around calls whose failure we can handle.
44 # Messier still, logging.getLogger('swiftclient') doesn't necessarily
45 # refer to the Logger instance actually being used by swiftclient, so we
46 # have to use swiftclient.logger directly.
47 old_disabled = swiftclient.logger.disabled
48 try:
49 swiftclient.logger.disabled = True
50 return func(*args, **kwargs)
51 finally:
52 swiftclient.logger.disabled = old_disabled
53
54
32def to_swift(log, start_lfc_id=None, end_lfc_id=None, remove_func=False):55def to_swift(log, start_lfc_id=None, end_lfc_id=None, remove_func=False):
33 '''Copy a range of Librarian files from disk into Swift.56 '''Copy a range of Librarian files from disk into Swift.
3457
@@ -118,7 +141,7 @@
118 container, obj_name = swift_location(lfc)141 container, obj_name = swift_location(lfc)
119142
120 try:143 try:
121 swift_connection.head_container(container)144 quiet_swiftclient(swift_connection.head_container, container)
122 log.debug2('{0} container already exists'.format(container))145 log.debug2('{0} container already exists'.format(container))
123 except swiftclient.ClientException as x:146 except swiftclient.ClientException as x:
124 if x.http_status != 404:147 if x.http_status != 404:
@@ -127,7 +150,8 @@
127 swift_connection.put_container(container)150 swift_connection.put_container(container)
128151
129 try:152 try:
130 headers = swift_connection.head_object(container, obj_name)153 headers = quiet_swiftclient(
154 swift_connection.head_object, container, obj_name)
131 log.debug(155 log.debug(
132 "{0} already exists in Swift({1}, {2})".format(156 "{0} already exists in Swift({1}, {2})".format(
133 lfc, container, obj_name))157 lfc, container, obj_name))
@@ -188,7 +212,7 @@
188 assert segment <= 9999, 'Insane number of segments'212 assert segment <= 9999, 'Insane number of segments'
189 seg_name = '%s/%04d' % (obj_name, segment)213 seg_name = '%s/%04d' % (obj_name, segment)
190 seg_size = min(fs_size - fs_file.tell(), MAX_SWIFT_OBJECT_SIZE)214 seg_size = min(fs_size - fs_file.tell(), MAX_SWIFT_OBJECT_SIZE)
191 md5_stream = HashStream(fs_file)215 md5_stream = HashStream(fs_file, length=seg_size)
192 swift_md5_hash = swift_connection.put_object(216 swift_md5_hash = swift_connection.put_object(
193 container, seg_name, md5_stream, seg_size)217 container, seg_name, md5_stream, seg_size)
194 segment_md5_hash = md5_stream.hash.hexdigest()218 segment_md5_hash = md5_stream.hash.hexdigest()
@@ -304,13 +328,20 @@
304328
305class HashStream:329class HashStream:
306 """Read a file while calculating a checksum as we go."""330 """Read a file while calculating a checksum as we go."""
307 def __init__(self, stream, hash_factory=hashlib.md5):331 def __init__(self, stream, length=None, hash_factory=hashlib.md5):
308 self._stream = stream332 self._stream = stream
333 self._length = self._remaining = length
309 self.hash_factory = hash_factory334 self.hash_factory = hash_factory
310 self.hash = hash_factory()335 self.hash = hash_factory()
311336
312 def read(self, size=-1):337 def read(self, size=-1):
338 if self._remaining is not None:
339 if self._remaining <= 0:
340 return ''
341 size = min(size, self._remaining)
313 chunk = self._stream.read(size)342 chunk = self._stream.read(size)
343 if self._remaining is not None:
344 self._remaining -= len(chunk)
314 self.hash.update(chunk)345 self.hash.update(chunk)
315 return chunk346 return chunk
316347
@@ -320,6 +351,8 @@
320 def seek(self, offset):351 def seek(self, offset):
321 """Seek to offset, and reset the hash."""352 """Seek to offset, and reset the hash."""
322 self.hash = self.hash_factory()353 self.hash = self.hash_factory()
354 if self._remaining is not None:
355 self._remaining = self._length - offset
323 return self._stream.seek(offset)356 return self._stream.seek(offset)
324357
325358
326359
=== modified file 'lib/lp/services/librarianserver/tests/test_gc.py'
--- lib/lp/services/librarianserver/tests/test_gc.py 2018-01-02 16:10:26 +0000
+++ lib/lp/services/librarianserver/tests/test_gc.py 2018-02-13 16:28:38 +0000
@@ -728,7 +728,8 @@
728 name += suffix728 name += suffix
729 with swift.connection() as swift_connection:729 with swift.connection() as swift_connection:
730 try:730 try:
731 swift_connection.head_object(container, name)731 swift.quiet_swiftclient(
732 swift_connection.head_object, container, name)
732 return True733 return True
733 except swiftclient.ClientException as x:734 except swiftclient.ClientException as x:
734 if x.http_status == 404:735 if x.http_status == 404:
735736
=== modified file 'lib/lp/services/librarianserver/tests/test_swift.py'
--- lib/lp/services/librarianserver/tests/test_swift.py 2018-01-02 16:10:26 +0000
+++ lib/lp/services/librarianserver/tests/test_swift.py 2018-02-13 16:28:38 +0000
@@ -1,4 +1,4 @@
1# Copyright 2013 Canonical Ltd. This software is licensed under the1# Copyright 2013-2017 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Librarian disk to Swift storage tests."""4"""Librarian disk to Swift storage tests."""
@@ -19,14 +19,17 @@
19from lp.services.features.testing import FeatureFixture19from lp.services.features.testing import FeatureFixture
20from lp.services.librarian.client import LibrarianClient20from lp.services.librarian.client import LibrarianClient
21from lp.services.librarian.model import LibraryFileAlias21from lp.services.librarian.model import LibraryFileAlias
22from lp.services.librarianserver import swift
22from lp.services.librarianserver.storage import LibrarianStorage23from lp.services.librarianserver.storage import LibrarianStorage
23from lp.services.log.logger import BufferLogger24from lp.services.log.logger import BufferLogger
24from lp.testing import TestCase25from lp.testing import TestCase
25from lp.testing.layers import BaseLayer, LaunchpadZopelessLayer, LibrarianLayer26from lp.testing.layers import (
27 BaseLayer,
28 LaunchpadZopelessLayer,
29 LibrarianLayer,
30 )
26from lp.testing.swift.fixture import SwiftFixture31from lp.testing.swift.fixture import SwiftFixture
2732
28from lp.services.librarianserver import swift
29
3033
31class TestFeedSwift(TestCase):34class TestFeedSwift(TestCase):
32 layer = LaunchpadZopelessLayer35 layer = LaunchpadZopelessLayer
@@ -272,8 +275,8 @@
272 _, obj2 = swift_client.get_object(container, '{0}/0001'.format(name))275 _, obj2 = swift_client.get_object(container, '{0}/0001'.format(name))
273 _, obj3 = swift_client.get_object(container, '{0}/0002'.format(name))276 _, obj3 = swift_client.get_object(container, '{0}/0002'.format(name))
274 self.assertRaises(277 self.assertRaises(
275 swiftclient.ClientException, swift_client.get_object,278 swiftclient.ClientException, swift.quiet_swiftclient,
276 container, '{0}/0003'.format(name))279 swift_client.get_object, container, '{0}/0003'.format(name))
277280
278 # Our object round tripped281 # Our object round tripped
279 self.assertEqual(obj1 + obj2 + obj3, expected_content)282 self.assertEqual(obj1 + obj2 + obj3, expected_content)
@@ -293,7 +296,8 @@
293296
294 def test_partial_read(self):297 def test_partial_read(self):
295 empty_sha1 = 'da39a3ee5e6b4b0d3255bfef95601890afd80709'298 empty_sha1 = 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
296 s = swift.HashStream(StringIO('make me another coffee'), hashlib.sha1)299 s = swift.HashStream(
300 StringIO('make me another coffee'), hash_factory=hashlib.sha1)
297 self.assertEqual(s.hash.hexdigest(), empty_sha1)301 self.assertEqual(s.hash.hexdigest(), empty_sha1)
298 chunk = s.read(4)302 chunk = s.read(4)
299 self.assertEqual(chunk, 'make')303 self.assertEqual(chunk, 'make')
@@ -304,6 +308,21 @@
304 self.assertEqual(s.hash.hexdigest(),308 self.assertEqual(s.hash.hexdigest(),
305 '8c826e573016ce05f3968044f82507b46fd2aa93')309 '8c826e573016ce05f3968044f82507b46fd2aa93')
306310
311 def test_limited_length(self):
312 base_stream = StringIO('make me a coffee')
313 s = swift.HashStream(base_stream, length=8)
314 chunk = s.read(4)
315 self.assertEqual(chunk, 'make')
316 self.assertEqual(s.hash.hexdigest(),
317 '099dafc678df7d266c25f95ccf6cde22')
318 chunk = s.read(8)
319 self.assertEqual(chunk, ' me ')
320 self.assertEqual(s.hash.hexdigest(),
321 '10a0334e435b75f35b1923842bd87f81')
322 self.assertEqual(s.read(), '')
323 self.assertEqual(s.tell(), 8)
324 self.assertEqual(base_stream.tell(), 8)
325
307 def test_tell(self):326 def test_tell(self):
308 s = swift.HashStream(StringIO('hurry up with that coffee'))327 s = swift.HashStream(StringIO('hurry up with that coffee'))
309 self.assertEqual(s.tell(), 0)328 self.assertEqual(s.tell(), 0)
310329
=== modified file 'lib/lp/testing/swift/fakeswift.py'
--- lib/lp/testing/swift/fakeswift.py 2017-12-07 12:05:13 +0000
+++ lib/lp/testing/swift/fakeswift.py 2018-02-13 16:28:38 +0000
@@ -557,17 +557,33 @@
557 """Compute service catalog for the given request and tenant."""557 """Compute service catalog for the given request and tenant."""
558 port = request.transport.socket.getsockname()[1]558 port = request.transport.socket.getsockname()[1]
559 tenant_id = self.tenants[tenant]["id"]559 tenant_id = self.tenants[tenant]["id"]
560 base_url = "http://%s:%d/swift/v1" % (self.hostname, port)560 base_url = "http://%s:%d" % (self.hostname, port)
561 keystone_base_url = "%s/keystone/v2.0" % base_url
562 swift_base_url = "%s/swift/v1" % base_url
561 catalog = [563 catalog = [
562 {"endpoints": [564 {
563 {"adminURL": base_url,565 "endpoints": [{
564 "id": uuid.uuid4().hex,566 "adminURL": keystone_base_url,
565 "internalURL": base_url + "/AUTH_" + tenant_id,567 "id": uuid.uuid4().hex,
566 "publicURL": base_url + "/AUTH_" + tenant_id,568 "internalURL": keystone_base_url,
567 "region": DEFAULT_REGION}569 "publicURL": keystone_base_url,
568 ],570 "region": DEFAULT_REGION,
569 "endpoints_links": [],571 }],
570 "name": "swift",572 "endpoints_links": [],
571 "type": "object-store"573 "name": "keystone",
572 }]574 "type": "identity",
575 },
576 {
577 "endpoints": [{
578 "adminURL": swift_base_url,
579 "id": uuid.uuid4().hex,
580 "internalURL": swift_base_url + "/AUTH_" + tenant_id,
581 "publicURL": swift_base_url + "/AUTH_" + tenant_id,
582 "region": DEFAULT_REGION,
583 }],
584 "endpoints_links": [],
585 "name": "swift",
586 "type": "object-store",
587 },
588 ]
573 return catalog589 return catalog
574590
=== modified file 'lib/lp/testing/swift/tests/test_fixture.py'
--- lib/lp/testing/swift/tests/test_fixture.py 2018-01-02 16:10:26 +0000
+++ lib/lp/testing/swift/tests/test_fixture.py 2018-02-13 16:28:38 +0000
@@ -8,9 +8,10 @@
88
9from datetime import datetime9from datetime import datetime
10from hashlib import md510from hashlib import md5
11import httplib
1211
12from requests.exceptions import ConnectionError
13from swiftclient import client as swiftclient13from swiftclient import client as swiftclient
14from swiftclient.exceptions import ClientException
14from testtools.matchers import (15from testtools.matchers import (
15 GreaterThan,16 GreaterThan,
16 LessThan,17 LessThan,
@@ -200,14 +201,14 @@
200 # authenticated.201 # authenticated.
201 self.swift_fixture.shutdown()202 self.swift_fixture.shutdown()
202 self.assertRaises(203 self.assertRaises(
203 httplib.HTTPException,204 ConnectionError,
204 client.get_object, "size", str(size))205 client.get_object, "size", str(size))
205206
206 # And even if we bring it back up, existing connections207 # And even if we bring it back up, existing connections
207 # continue to fail208 # continue to fail
208 self.swift_fixture.startup()209 self.swift_fixture.startup()
209 self.assertRaises(210 self.assertRaises(
210 httplib.HTTPException,211 ClientException,
211 client.get_object, "size", str(size))212 client.get_object, "size", str(size))
212213
213 # But fresh connections are fine.214 # But fresh connections are fine.
214215
=== modified file 'lib/lp_sitecustomize.py'
--- lib/lp_sitecustomize.py 2017-12-19 12:32:57 +0000
+++ lib/lp_sitecustomize.py 2018-02-13 16:28:38 +0000
@@ -91,9 +91,13 @@
91 Logger, which is unfortunate as we disable them in the handler. Not91 Logger, which is unfortunate as we disable them in the handler. Not
92 only does swiftclient then emit lots of noise, but it also turns92 only does swiftclient then emit lots of noise, but it also turns
93 keystoneclient debugging on.93 keystoneclient debugging on.
94
95 keystoneclient logs credentials at DEBUG.
94 """96 """
95 swiftclient_logger = logging.getLogger('swiftclient')97 swiftclient_logger = logging.getLogger('swiftclient')
96 swiftclient_logger.setLevel(logging.INFO)98 swiftclient_logger.setLevel(logging.INFO)
99 keystoneclient_logger = logging.getLogger('keystoneclient')
100 keystoneclient_logger.setLevel(logging.INFO)
97101
98102
99def silence_zcml_logger():103def silence_zcml_logger():