openstack-common: timeutils and importutils seperated out

Signed-off-by: Angus Salkeld <asalkeld@redhat.com>
This commit is contained in:
Angus Salkeld 2012-04-27 10:21:43 +10:00
parent a9a6906a6e
commit 1f141a6d04
12 changed files with 137 additions and 119 deletions

View File

@ -17,7 +17,7 @@
Middleware that attaches a context to the WSGI request
"""
from heat.common import utils
from heat.common import importutils
from heat.common import wsgi
from heat.common import context
@ -35,7 +35,7 @@ class ContextMiddleware(wsgi.Middleware):
# Determine the context class to use
ctxcls = context.RequestContext
if 'context_class' in self.options:
ctxcls = utils.import_class(self.options['context_class'])
ctxcls = importutils.import_class(self.options['context_class'])
return ctxcls(*args, **kwargs)

View File

@ -16,7 +16,7 @@
from heat.common import exception
from heat.common import wsgi
from heat.openstack.common import cfg
from heat.openstack.common import utils
from heat.openstack.common import importutils
class RequestContext(object):
@ -64,7 +64,7 @@ class ContextMiddleware(wsgi.Middleware):
# Determine the context class to use
self.ctxcls = RequestContext
if 'context_class' in local_conf:
self.ctxcls = utils.import_class(local_conf['context_class'])
self.ctxcls = importutils.import_class(local_conf['context_class'])
super(ContextMiddleware, self).__init__(app)

View File

@ -30,6 +30,7 @@ from eventlet import semaphore
from eventlet.green import subprocess
from heat.openstack.common import exception
from heat.openstack.common import timeutils
PERFECT_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%f"
@ -71,7 +72,7 @@ def gen_uuid():
def strtime(at=None, fmt=PERFECT_TIME_FORMAT):
"""Returns formatted utcnow."""
if not at:
at = utcnow()
at = timeutils.utcnow()
return at.strftime(fmt)
@ -80,16 +81,6 @@ def parse_strtime(timestr, fmt=PERFECT_TIME_FORMAT):
return datetime.datetime.strptime(timestr, fmt)
def isotime(at=None):
"""Stringify time in ISO 8601 format"""
if not at:
at = datetime.datetime.utcnow()
str = at.strftime(ISO_TIME_FORMAT)
tz = at.tzinfo.tzname(None) if at.tzinfo else 'UTC'
str += ('Z' if tz == 'UTC' else tz)
return str
class LoopingCallDone(Exception):
"""Exception to break out and stop a LoopingCall.

View File

@ -41,6 +41,7 @@ import webob.exc
from heat.common import exception
from heat.openstack.common import cfg
from heat.openstack.common import importutils
from heat.openstack.common import utils
bind_opts = [
@ -544,7 +545,7 @@ class BasePasteFactory(object):
we strip() the value before using it.
"""
class_name = local_conf[self.KEY].replace(':', '.').strip()
return utils.import_class(class_name)
return importutils.import_class(class_name)
class AppFactory(BasePasteFactory):

View File

@ -24,6 +24,7 @@ import logging
from heat.openstack.common import local
from heat.openstack.common import utils
from heat.openstack.common import timeutils
from heat.common import utils as heat_utils
@ -73,7 +74,7 @@ class RequestContext(object):
self.read_deleted = read_deleted
self.remote_address = remote_address
if not timestamp:
timestamp = utils.utcnow()
timestamp = timeutils.utcnow()
if isinstance(timestamp, basestring):
timestamp = heat_utils.parse_strtime(timestamp)
self.timestamp = timestamp

View File

@ -22,7 +22,7 @@ from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.schema import ForeignKeyConstraint
from sqlalchemy import types as types
from json import dumps, loads
from heat.openstack.common import utils
from heat.openstack.common import timeutils
from heat.db.sqlalchemy.session import get_session
from sqlalchemy.orm.session import Session
@ -43,8 +43,8 @@ class HeatBase(object):
"""Base class for Heat Models."""
__table_args__ = {'mysql_engine': 'InnoDB'}
__table_initialized__ = False
created_at = Column(DateTime, default=utils.utcnow)
updated_at = Column(DateTime, onupdate=utils.utcnow)
created_at = Column(DateTime, default=timeutils.utcnow)
updated_at = Column(DateTime, onupdate=timeutils.utcnow)
def save(self, session=None):
"""Save this object."""
@ -64,7 +64,7 @@ class HeatBase(object):
def delete(self, session=None):
"""Delete this object."""
self.deleted = True
self.deleted_at = utils.utcnow()
self.deleted_at = timeutils.utcnow()
self.save(session=session)
def __setitem__(self, key, value):

View File

@ -0,0 +1,45 @@
# 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.
"""
Import related utilities and helper functions.
"""
import sys
from heat.openstack.common import exception
def import_class(import_str):
"""Returns a class from a string including module and class"""
mod_str, _sep, class_str = import_str.rpartition('.')
try:
__import__(mod_str)
return getattr(sys.modules[mod_str], class_str)
except (ImportError, ValueError, AttributeError):
raise exception.NotFound('Class %s cannot be found' % class_str)
def import_object(import_str, *args, **kwargs):
"""Import a class and return an instance of it."""
return import_class(import_str)(*args, **kwargs)
def import_module(import_str):
"""Import a module."""
__import__(import_str)
return sys.modules[import_str]

View File

@ -0,0 +1,73 @@
# 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 datetime
import iso8601
TIME_FORMAT = "%Y-%m-%dT%H:%M:%S"
def isotime(at=None):
"""Stringify time in ISO 8601 format"""
if not at:
at = datetime.datetime.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 normalize_time(timestamp):
"""Normalize time in arbitrary timezone to UTC"""
offset = timestamp.utcoffset()
return timestamp.replace(tzinfo=None) - offset if offset else timestamp
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 clear_time_override():
"""Remove the overridden time."""
utcnow.override_time = None

View File

@ -19,21 +19,17 @@
System-level utilities and helper functions.
"""
import datetime
import logging
import os
import random
import shlex
import sys
from eventlet import greenthread
from eventlet.green import subprocess
import iso8601
from heat.openstack.common import exception
TIME_FORMAT = "%Y-%m-%dT%H:%M:%S"
LOG = logging.getLogger(__name__)
@ -142,92 +138,3 @@ def execute(*cmd, **kwargs):
# call clean something up in between calls, without
# it two execute calls in a row hangs the second one
greenthread.sleep(0)
def import_class(import_str):
"""Returns a class from a string including module and class"""
mod_str, _sep, class_str = import_str.rpartition('.')
try:
__import__(mod_str)
return getattr(sys.modules[mod_str], class_str)
except (ImportError, ValueError, AttributeError):
raise exception.NotFound('Class %s cannot be found' % class_str)
def import_object(import_str):
"""Returns an object including a module or module and class"""
try:
__import__(import_str)
return sys.modules[import_str]
except ImportError:
return import_class(import_str)
def isotime(at=None):
"""Stringify time in ISO 8601 format"""
if not at:
at = datetime.datetime.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 normalize_time(timestamp):
"""Normalize time in arbitrary timezone to UTC"""
offset = timestamp.utcoffset()
return timestamp.replace(tzinfo=None) - offset if offset else timestamp
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 clear_time_override():
"""Remove the overridden time."""
utcnow.override_time = None
def auth_str_equal(provided, known):
"""Constant-time string comparison.
:params provided: the first string
:params known: the second string
:return: True if the strings are equal.
This function takes two strings and compares them. It is intended to be
used when doing a comparison for authentication purposes to help guard
against timing attacks. When using the function for this purpose, always
provide the user-provided password as the first argument. The time this
function will take is always a factor of the length of this string.
"""
result = 0
p_len = len(provided)
k_len = len(known)
for i in xrange(p_len):
a = ord(provided[i]) if i < p_len else 0
b = ord(known[i]) if i < k_len else 0
result |= a ^ b
return (p_len == k_len) & (result == 0)

View File

@ -19,7 +19,7 @@
import logging
from heat.openstack.common import cfg
from heat.openstack.common import utils
from heat.openstack.common import importutils
LOG = logging.getLogger(__name__)
@ -192,7 +192,7 @@ def configure(conf):
LOG.debug(_("Configuring RPC %s") % conf.rpc_backend)
global _RPCIMPL
_RPCIMPL = utils.import_object(conf.rpc_backend)
_RPCIMPL = importutils.import_module(conf.rpc_backend)
def _get_impl():

View File

@ -27,7 +27,7 @@ import logging
import greenlet
from heat.openstack.common import cfg
from heat.openstack.common import utils
from heat.openstack.common import importutils
from heat.common import utils as heat_utils
from heat.common import exception
@ -108,7 +108,7 @@ class Service(object):
self.binary = binary
self.topic = topic
self.manager_class_name = manager
manager_class = utils.import_class(self.manager_class_name)
manager_class = importutils.import_class(self.manager_class_name)
self.manager = manager_class(host=self.host, *args, **kwargs)
self.periodic_interval = periodic_interval
super(Service, self).__init__(*args, **kwargs)

View File

@ -1,7 +1,7 @@
[DEFAULT]
# The list of modules to copy from openstack-common
modules=cfg,local,iniparser,utils,exception
modules=cfg,local,iniparser,utils,exception,timeutils,importutils
# The base module to hold the copy of openstack.common
base=heat