attachment_swift: share a session for all connections

OVH's Swift applies a rate limit on the authentication.

attachment_swift authenticates again each time it has to read/write an
attachment. When running upgrades on upgrades of files or installing a
new DB, at some point, we get rejected with HTTP 429.

This commit introduces a shared storage for Swift Session. All
connections will reuses the same authentication token created the first
time a connection needs a Session.

Note: needs python-swiftclient>=3.7.0 to have
https://github.com/openstack/python-swiftclient/commit/1971ef880ff225379d4a91f00f89f323a1605eeb
This commit is contained in:
Guewen Baconnier
2019-05-09 10:10:36 +02:00
parent 440600e89f
commit 8a4e9d1f84
3 changed files with 108 additions and 16 deletions
+43 -6
View File
@@ -3,11 +3,16 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
import base64
import mock
import os
from mock import patch
import keystoneauth1
from odoo.addons.base.tests.test_ir_attachment import TestIrAttachment
from ..swift_uri import SwiftUri
from odoo.addons.attachment_swift.models.ir_attachment import SwiftSessionStore
from odoo.addons.attachment_swift.swift_uri import SwiftUri
class TestAttachmentSwift(TestIrAttachment):
@@ -17,6 +22,34 @@ class TestAttachmentSwift(TestIrAttachment):
self.env['ir.config_parameter'].set_param('ir_attachment.location',
'swift')
def test_session_store_get_session(self):
auth_url = 'auth_url'
username = 'username'
password = 'password'
tenant_name = 'tenant_name'
store = SwiftSessionStore()
session = store.get_session(
auth_url=auth_url,
username=username,
password=password,
tenant_name=tenant_name,
)
self.assertEqual(session.auth.auth_url, auth_url)
self.assertEqual(session.auth.username, username)
self.assertEqual(session.auth.password, password)
self.assertEqual(session.auth.tenant_name, tenant_name)
# get the same session on a second call
self.assertEqual(
store.get_session(
auth_url=auth_url,
username=username,
password=password,
tenant_name=tenant_name,
),
session
)
@patch('swiftclient.client')
def test_connection(self, mock_swift_client):
""" Test the connection to the store"""
@@ -28,13 +61,17 @@ class TestAttachmentSwift(TestIrAttachment):
attachment = self.Attachment
attachment._get_swift_connection()
mock_swift_client.Connection.assert_called_once_with(
authurl=os.environ.get('SWIFT_AUTH_URL'),
user=os.environ.get('SWIFT_ACCOUNT'),
key=os.environ.get('SWIFT_PASSWORD'),
tenant_name=os.environ.get('SWIFT_TENANT_NAME'),
auth_version='2.0',
session=mock.ANY,
os_options={'region_name': os.environ.get('SWIFT_REGION_NAME')},
)
__, kwargs = mock_swift_client.Connection.call_args
session = kwargs['session']
self.assertTrue(isinstance(session, keystoneauth1.session.Session))
self.assertEqual(session.auth.auth_url, os.environ['SWIFT_AUTH_URL'])
self.assertEqual(session.auth.username, os.environ['SWIFT_ACCOUNT'])
self.assertEqual(session.auth.password, os.environ['SWIFT_PASSWORD'])
self.assertEqual(session.auth.tenant_name,
os.environ['SWIFT_TENANT_NAME'])
def test_store_file_on_swift(self):
"""