Use keystoneauth v3 for Swift attachments

This commit is contained in:
Mussie Sirak
2020-03-04 13:04:50 +01:00
committed by Patrick Tombez
co-authored by Patrick Tombez
parent 0c9d5d6abe
commit 9d6e38381d
5 changed files with 244 additions and 18 deletions
+68 -11
View File
@@ -16,6 +16,7 @@ _logger = logging.getLogger(__name__)
try:
import swiftclient
import keystoneauth1
from swiftclient.exceptions import ClientException
except ImportError:
swiftclient = None
@@ -23,6 +24,54 @@ except ImportError:
_logger.debug("Cannot 'import swiftclient'.")
SWIFT_TIMEOUT = 15
class SwiftSessionStore(object):
"""Keep in memory the current Swift Auth session
The auth endpoint has a rate limit on swift, if every operation
on the filestore authenticate, the limit is exhausted and
operations rejected with an HTTP error code 429.
Swift connections can reuse the same session by asking a session
matching their connection parameters with ``get_session``.
The keystoneauth1's session automatically creates a new token
if the previous one is expired.
The best documentation I found about sessions is
https://docs.openstack.org/keystoneauth/latest/using-sessions.html
"""
def __init__(self):
self._sessions = {}
def _get_key(self, auth_url, username, password, project_name):
return (auth_url, username, password, project_name)
def get_session(self, auth_url=None, username=None, password=None,
project_name=None):
key = self._get_key(auth_url, username, password, project_name)
session = self._sessions.get(key)
if not session:
auth = keystoneauth1.identity.v3.Password(
username=username,
password=password,
project_name=project_name,
auth_url=auth_url,
)
session = keystoneauth1.session.Session(
auth=auth,
timeout=SWIFT_TIMEOUT,
)
self._sessions[key] = session
return session
swift_session_store = SwiftSessionStore()
class IrAttachment(osv.osv):
_inherit = 'ir.attachment'
@@ -34,26 +83,34 @@ class IrAttachment(osv.osv):
host = os.environ.get('SWIFT_AUTH_URL')
account = os.environ.get('SWIFT_ACCOUNT')
password = os.environ.get('SWIFT_PASSWORD')
tenant_name = os.environ.get('SWIFT_TENANT_NAME')
project_name = os.environ.get('SWIFT_PROJECT_NAME')
if not project_name and os.environ.get('SWIFT_TENANT_NAME'):
project_name = os.environ['SWIFT_TENANT_NAME']
_logger.warning(
"SWIFT_TENANT_NAME is deprecated and "
"must be replaced by SWIFT_PROJECT_NAME"
)
region = os.environ.get('SWIFT_REGION_NAME')
os_options = {}
if region:
os_options['region_name'] = region
if not (host and account and password and tenant_name):
if not (host and account and password and project_name):
raise except_orm(
_("Error"),
_("Problem connecting to Swift store, are the env variables "
"(SWIFT_AUTH_URL, SWIFT_ACCOUNT, SWIFT_PASSWORD, "
"SWIFT_TENANT_NAME) properly set?")
)
"SWIFT_TENANT_NAME) properly set?"))
try:
conn = swiftclient.client.Connection(authurl=host,
user=account,
key=password,
tenant_name=tenant_name,
auth_version='2.0',
os_options=os_options,
)
session = swift_session_store.get_session(
username=account,
password=password,
project_name=project_name,
auth_url=host,
)
conn = swiftclient.client.Connection(
session=session,
os_options=os_options,
)
except ClientException:
_logger.exception('Error connecting to Swift object store')
raise except_orm(