summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhongyue Luo <lzyeval@gmail.com>2012-06-05 09:11:44 +0800
committerZhongyue Luo <lzyeval@gmail.com>2012-06-29 06:38:49 +0800
commitc79d93bfbc8a79617a6d3ef4e36fb5de55217d02 (patch)
tree1940868376325627fe4f16091d4b8e784e0c69fe
parent8cd73c75cec35d4df49891ee4c36102b4c8d96ff (diff)
downloadkeystone-c79d93bfbc8a79617a6d3ef4e36fb5de55217d02.tar.gz
keystone-c79d93bfbc8a79617a6d3ef4e36fb5de55217d02.tar.xz
keystone-c79d93bfbc8a79617a6d3ef4e36fb5de55217d02.zip
Keystone should use openstack.common.timeutils
Implements blueprint use-common-timeutils 1. Edit openstack-common.conf and import keystone/openstack/common/timeutils.py 2. Replace datetime.utcnow with timeutils.utcnow 3. Replace utils.isotime with timeutils.isotime 4. Remove utils.isotime in common/utils.py and datetime related unittest Change-Id: I4f5a63a368fde8787a0dc0a817c940de685b9ca2
-rw-r--r--keystone/common/utils.py11
-rw-r--r--keystone/openstack/common/timeutils.py109
-rw-r--r--keystone/service.py3
-rw-r--r--keystone/token/backends/kvs.py7
-rw-r--r--keystone/token/backends/sql.py6
-rw-r--r--keystone/token/core.py3
-rw-r--r--openstack-common.conf2
-rw-r--r--tests/test_backend.py4
-rw-r--r--tests/test_backend_memcache.py6
-rw-r--r--tests/test_utils.py9
10 files changed, 125 insertions, 35 deletions
diff --git a/keystone/common/utils.py b/keystone/common/utils.py
index 7f665a59..19749764 100644
--- a/keystone/common/utils.py
+++ b/keystone/common/utils.py
@@ -39,7 +39,6 @@ config.register_int('crypt_strength', default=40000)
LOG = logging.getLogger(__name__)
-ISO_TIME_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
MAX_PASSWORD_LENGTH = 4096
@@ -232,16 +231,6 @@ def git(*args):
return check_output(['git'] + list(args))
-def isotime(dt_obj):
- """Format datetime object as ISO compliant string.
-
- :param dt_obj: datetime.datetime object
- :returns: string representation of datetime object
-
- """
- return dt_obj.strftime(ISO_TIME_FORMAT)
-
-
def unixtime(dt_obj):
"""Format datetime object as unix timestamp
diff --git a/keystone/openstack/common/timeutils.py b/keystone/openstack/common/timeutils.py
new file mode 100644
index 00000000..5eeaf70a
--- /dev/null
+++ b/keystone/openstack/common/timeutils.py
@@ -0,0 +1,109 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 OpenStack LLC.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""
+Time related utilities and helper functions.
+"""
+
+import calendar
+import datetime
+import time
+
+import iso8601
+
+
+TIME_FORMAT = "%Y-%m-%dT%H:%M:%S"
+PERFECT_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%f"
+
+
+def isotime(at=None):
+ """Stringify time in ISO 8601 format"""
+ if not at:
+ at = utcnow()
+ str = at.strftime(TIME_FORMAT)
+ tz = at.tzinfo.tzname(None) if at.tzinfo else 'UTC'
+ str += ('Z' if tz == 'UTC' else tz)
+ return str
+
+
+def parse_isotime(timestr):
+ """Parse time from ISO 8601 format"""
+ try:
+ return iso8601.parse_date(timestr)
+ except iso8601.ParseError as e:
+ raise ValueError(e.message)
+ except TypeError as e:
+ raise ValueError(e.message)
+
+
+def strtime(at=None, fmt=PERFECT_TIME_FORMAT):
+ """Returns formatted utcnow."""
+ if not at:
+ at = utcnow()
+ return at.strftime(fmt)
+
+
+def parse_strtime(timestr, fmt=PERFECT_TIME_FORMAT):
+ """Turn a formatted time back into a datetime."""
+ return datetime.datetime.strptime(timestr, fmt)
+
+
+def normalize_time(timestamp):
+ """Normalize time in arbitrary timezone to UTC"""
+ offset = timestamp.utcoffset()
+ return timestamp.replace(tzinfo=None) - offset if offset else timestamp
+
+
+def is_older_than(before, seconds):
+ """Return True if before is older than seconds."""
+ return utcnow() - before > datetime.timedelta(seconds=seconds)
+
+
+def utcnow_ts():
+ """Timestamp version of our utcnow function."""
+ return calendar.timegm(utcnow().timetuple())
+
+
+def utcnow():
+ """Overridable version of utils.utcnow."""
+ if utcnow.override_time:
+ return utcnow.override_time
+ return datetime.datetime.utcnow()
+
+
+utcnow.override_time = None
+
+
+def set_time_override(override_time=datetime.datetime.utcnow()):
+ """Override utils.utcnow to return a constant time."""
+ utcnow.override_time = override_time
+
+
+def advance_time_delta(timedelta):
+ """Advance overriden time using a datetime.timedelta."""
+ assert(not utcnow.override_time is None)
+ utcnow.override_time += timedelta
+
+
+def advance_time_seconds(seconds):
+ """Advance overriden time by seconds."""
+ advance_time_delta(datetime.timedelta(0, seconds))
+
+
+def clear_time_override():
+ """Remove the overridden time."""
+ utcnow.override_time = None
diff --git a/keystone/service.py b/keystone/service.py
index d7215198..913b8761 100644
--- a/keystone/service.py
+++ b/keystone/service.py
@@ -24,6 +24,7 @@ from keystone.common import utils
from keystone.common import wsgi
from keystone import exception
from keystone import identity
+from keystone.openstack.common import timeutils
from keystone import policy
from keystone import token
@@ -451,7 +452,7 @@ class TokenController(wsgi.Application):
metadata_ref = token_ref['metadata']
expires = token_ref['expires']
if expires is not None:
- expires = utils.isotime(expires)
+ expires = timeutils.isotime(expires)
o = {'access': {'token': {'id': token_ref['id'],
'expires': expires,
},
diff --git a/keystone/token/backends/kvs.py b/keystone/token/backends/kvs.py
index a61be955..442bd4b8 100644
--- a/keystone/token/backends/kvs.py
+++ b/keystone/token/backends/kvs.py
@@ -15,10 +15,10 @@
# under the License.
import copy
-import datetime
from keystone.common import kvs
from keystone import exception
+from keystone.openstack.common import timeutils
from keystone import token
@@ -29,8 +29,7 @@ class Token(kvs.Base, token.Driver):
token = self.db.get('token-%s' % token_id)
except exception.NotFound:
raise exception.TokenNotFound(token_id=token_id)
- if (token['expires'] is None
- or token['expires'] > datetime.datetime.utcnow()):
+ if token['expires'] is None or token['expires'] > timeutils.utcnow():
return token
else:
raise exception.TokenNotFound(token_id=token_id)
@@ -50,7 +49,7 @@ class Token(kvs.Base, token.Driver):
def list_tokens(self, user_id):
tokens = []
- now = datetime.datetime.utcnow()
+ now = timeutils.utcnow()
for token, user_ref in self.db.items():
if not token.startswith('token-'):
continue
diff --git a/keystone/token/backends/sql.py b/keystone/token/backends/sql.py
index 5ba5e3a9..59cc47ca 100644
--- a/keystone/token/backends/sql.py
+++ b/keystone/token/backends/sql.py
@@ -15,10 +15,10 @@
# under the License.
import copy
-import datetime
from keystone.common import sql
from keystone import exception
+from keystone.openstack.common import timeutils
from keystone import token
@@ -50,7 +50,7 @@ class Token(sql.Base, token.Driver):
def get_token(self, token_id):
session = self.get_session()
token_ref = session.query(TokenModel).filter_by(id=token_id).first()
- now = datetime.datetime.utcnow()
+ now = timeutils.utcnow()
if token_ref and (not token_ref.expires or now < token_ref.expires):
return token_ref.to_dict()
else:
@@ -80,7 +80,7 @@ class Token(sql.Base, token.Driver):
def list_tokens(self, user_id):
session = self.get_session()
tokens = []
- now = datetime.datetime.utcnow()
+ now = timeutils.utcnow()
for token_ref in session.query(TokenModel)\
.filter(TokenModel.expires > now):
token_ref_dict = token_ref.to_dict()
diff --git a/keystone/token/core.py b/keystone/token/core.py
index 0aa2ce41..aff59fba 100644
--- a/keystone/token/core.py
+++ b/keystone/token/core.py
@@ -21,6 +21,7 @@ import datetime
from keystone.common import manager
from keystone import config
from keystone import exception
+from keystone.openstack.common import timeutils
CONF = config.CONF
@@ -104,4 +105,4 @@ class Driver(object):
"""
expire_delta = datetime.timedelta(seconds=CONF.token.expiration)
- return datetime.datetime.utcnow() + expire_delta
+ return timeutils.utcnow() + expire_delta
diff --git a/openstack-common.conf b/openstack-common.conf
index b96d8123..6042cc6c 100644
--- a/openstack-common.conf
+++ b/openstack-common.conf
@@ -1,7 +1,7 @@
[DEFAULT]
# The list of modules to copy from openstack-common
-modules=cfg,importutils,iniparser,jsonutils,setup
+modules=cfg,importutils,iniparser,jsonutils,setup,timeutils
# The base module to hold the copy of openstack.common
base=keystone
diff --git a/tests/test_backend.py b/tests/test_backend.py
index 85cb4c31..83aabfda 100644
--- a/tests/test_backend.py
+++ b/tests/test_backend.py
@@ -18,6 +18,7 @@ import datetime
import uuid
from keystone import exception
+from keystone.openstack.common import timeutils
class IdentityTests(object):
@@ -553,8 +554,7 @@ class TokenTests(object):
def test_expired_token(self):
token_id = uuid.uuid4().hex
- expire_time = datetime.datetime.utcnow() - datetime.timedelta(
- minutes=1)
+ expire_time = timeutils.utcnow() - datetime.timedelta(minutes=1)
data = {'id': token_id, 'a': 'b', 'expires': expire_time}
data_ref = self.token_api.create_token(token_id, data)
self.assertDictEqual(data_ref, data)
diff --git a/tests/test_backend_memcache.py b/tests/test_backend_memcache.py
index 2c07580b..f18cc9ca 100644
--- a/tests/test_backend_memcache.py
+++ b/tests/test_backend_memcache.py
@@ -14,13 +14,13 @@
# License for the specific language governing permissions and limitations
# under the License.
-import datetime
-import time
import uuid
import memcache
+from keystone.common import utils
from keystone import exception
+from keystone.openstack.common import timeutils
from keystone import test
from keystone.token.backends import memcache as token_memcache
@@ -42,7 +42,7 @@ class MemcacheClient(object):
"""Retrieves the value for a key or None."""
self.check_key(key)
obj = self.cache.get(key)
- now = time.mktime(datetime.datetime.utcnow().utctimetuple())
+ now = utils.unixtime(timeutils.utcnow())
if obj and (obj[1] == 0 or obj[1] > now):
return obj[0]
else:
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 52efafcb..0c9c7757 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -29,8 +29,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import datetime
-
from keystone import test
from keystone.common import utils
@@ -60,13 +58,6 @@ class UtilsTestCase(test.TestCase):
self.assertTrue(utils.check_password(password, hashed))
self.assertFalse(utils.check_password(wrong, hashed))
- def test_isotime(self):
- dt = datetime.datetime(year=1987, month=10, day=13,
- hour=1, minute=2, second=3)
- output = utils.isotime(dt)
- expected = '1987-10-13T01:02:03Z'
- self.assertEqual(output, expected)
-
def test_auth_str_equal(self):
self.assertTrue(utils.auth_str_equal('abc123', 'abc123'))
self.assertFalse(utils.auth_str_equal('a', 'aaaaa'))