summaryrefslogtreecommitdiffstats
path: root/keystone
diff options
context:
space:
mode:
Diffstat (limited to 'keystone')
-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
6 files changed, 119 insertions, 20 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