Merge "Support timezone in memcached token backend"

This commit is contained in:
Jenkins 2013-09-05 16:27:03 +00:00 committed by Gerrit Code Review
commit 5e4914742e
4 changed files with 74 additions and 13 deletions

View File

@ -45,17 +45,6 @@ Stop the process using ``Control-C``.
If you have not already configured Keystone, it may not start as expected.
Memcached and System Time
=========================
If using `memcached`_ with Keystone - e.g. using the memcache token
driver or the ``auth_token`` middleware - ensure that the system time
of memcached hosts is set to UTC. Memcached uses the host's system
time in determining whether a key has expired, whereas Keystone sets
key expiry in UTC. The timezone used by Keystone and memcached must
match if key expiry is to behave as expected.
.. _`memcached`: http://memcached.org/
Configuration Files
===================

View File

@ -18,12 +18,12 @@
# License for the specific language governing permissions and limitations
# under the License.
import calendar
import grp
import hashlib
import json
import os
import pwd
import time
import passlib.hash
@ -221,7 +221,7 @@ def unixtime(dt_obj):
:returns: float
"""
return time.mktime(dt_obj.utctimetuple())
return calendar.timegm(dt_obj.utctimetuple())
def auth_str_equal(provided, known):

View File

@ -30,6 +30,7 @@ from keystone import token
from keystone.token.backends import memcache as token_memcache
import test_backend
import test_utils
class MemcacheClient(object):
@ -185,3 +186,33 @@ class MemcacheToken(test.TestCase, test_backend.TokenTests):
exception.UnexpectedError,
self.token_api.driver._update_user_list_with_cas,
user_key, token_data)
def test_token_expire_timezone(self):
@test_utils.timezone
def _create_token(expire_time):
token_id = uuid.uuid4().hex
user_id = unicode(uuid.uuid4().hex)
data = {'id': token_id, 'a': 'b', 'user': {'id': user_id},
'expires': expire_time
}
self.token_api.create_token(token_id, data)
return data
for d in ['+0', '-11', '-8', '-5', '+5', '+8', '+14']:
test_utils.TZ = 'UTC' + d
expire_time = timeutils.utcnow() + \
datetime.timedelta(minutes=1)
data_in = _create_token(expire_time)
data_get = None
data_get = self.token_api.get_token(data_in['id'])
self.assertIsNotNone(data_get, "TZ=%s" % test_utils.TZ)
self.assertEquals(data_in['id'], data_get['id'],
"TZ=%s" % test_utils.TZ)
expire_time_expired = timeutils.utcnow() + \
datetime.timedelta(minutes=-1)
data_in = _create_token(expire_time_expired)
self.assertRaises(exception.TokenNotFound,
self.token_api.get_token, data_in['id'])

View File

@ -29,10 +29,37 @@
# License for the specific language governing permissions and limitations
# under the License.
import datetime
import functools
import os
import time
from keystone.tests import core as test
from keystone.common import utils
TZ = None
def timezone(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
tz_original = os.environ.get('TZ')
try:
if TZ:
os.environ['TZ'] = TZ
time.tzset()
return func(*args, **kwargs)
finally:
if TZ:
if tz_original:
os.environ['TZ'] = tz_original
else:
if 'TZ' in os.environ:
del os.environ['TZ']
time.tzset()
return wrapper
class UtilsTestCase(test.TestCase):
def test_hash(self):
@ -64,3 +91,17 @@ class UtilsTestCase(test.TestCase):
self.assertFalse(utils.auth_str_equal('a', 'aaaaa'))
self.assertFalse(utils.auth_str_equal('aaaaa', 'a'))
self.assertFalse(utils.auth_str_equal('ABC123', 'abc123'))
def test_unixtime(self):
global TZ
@timezone
def _test_unixtime():
epoch = utils.unixtime(dt)
self.assertEquals(epoch, epoch_ans, "TZ=%s" % TZ)
dt = datetime.datetime(1970, 1, 2, 3, 4, 56, 0)
epoch_ans = 56 + 4 * 60 + 3 * 3600 + 86400
for d in ['+0', '-11', '-8', '-5', '+5', '+8', '+14']:
TZ = 'UTC' + d
_test_unixtime()