Add dummy domain_id column to cached role

When token caching is turned on, upgrading from stable/liberty to
stable/mitaka or master causes tokens to fail to be issued for the
time-to-live of the cache. This is because as part of the token
issuance the token's role is looked up, and the cached version of the
role immediately after upgrade does not have a domain_id field, even
though that column was successfully added to the role database. This
patch hacks around that by artificially adding a null domain_id value
to the role reference.

This must be done in the manager, as opposed to the driver, because it
is the manager that is caching the value and so modifying the value
returned by the driver has no effect.

Change-Id: I55c791486f2a26ae995f693370b016895176a16f
Closes-bug: #1592169
This commit is contained in:
Colleen Murphy 2016-07-26 13:02:42 -07:00
parent 8a669fabad
commit bc99dc7677
1 changed files with 26 additions and 0 deletions

View File

@ -15,6 +15,7 @@
"""Main entry point into the Assignment service."""
import copy
import functools
from oslo_cache import core as oslo_cache
from oslo_log import log
@ -1159,6 +1160,31 @@ class RoleManager(manager.Manager):
elif not isinstance(self.driver, role_base.RoleDriverV9):
raise exception.UnsupportedDriverVersion(driver=role_driver)
def _append_null_domain_id(f):
"""Append a domain_id field to a role dict if it is not already there.
When caching is turned on, upgrading from liberty to
mitaka or master causes tokens to fail to be issued for the
time-to-live of the cache. This is because as part of the token
issuance the token's role is looked up, and the cached version of the
role immediately after upgrade does not have a domain_id field, even
though that column was successfully added to the role database. This
decorator artificially adds a null domain_id value to the role
reference so that the cached value acts like the updated schema.
Note: This decorator must appear before the @MEMOIZE decorator
because it operates on the cached value returned by the MEMOIZE
function.
"""
@functools.wraps(f)
def wrapper(self, *args, **kwargs):
ref = f(self, *args, **kwargs)
if 'domain_id' not in ref:
ref['domain_id'] = None
return ref
return wrapper
@_append_null_domain_id
@MEMOIZE
def get_role(self, role_id):
return self.driver.get_role(role_id)