Replaces functions in utils.py with openstack/common/timeutils.py

Fixes bug #1008628

1. Edit openstack-common.conf and import nova/openstack/common/timeutils.py
2. Move time related functions from utils.py to timeutils.py
3. Replace following functions in utils.py with timeutils.py
- isotime
- parse_isotime
- strtime
- parse_strtime
- normalize_time
- is_older_than
- utcnow_ts
- utcnow
- set_time_override
- advance_time_delta
- advance_time_seconds
- clear_time_override
4. Remove datetime related functions and datetime related unittests

Change-Id: I9a92be286fb071b6237dd39495d88dae106e2ce0
This commit is contained in:
Zhongyue Luo 2012-06-06 10:32:49 +08:00
parent c8440962a1
commit 2970d3f512
17 changed files with 163 additions and 127 deletions

View File

@ -90,6 +90,7 @@ from nova import log as logging
from nova.openstack.common import cfg
from nova.openstack.common import importutils
from nova.openstack.common import jsonutils
from nova.openstack.common import timeutils
from nova import quota
from nova import rpc
from nova.scheduler import rpcapi as scheduler_rpcapi
@ -968,7 +969,7 @@ class ServiceCommands(object):
Show a list of all running services. Filter by host & service name.
"""
ctxt = context.get_admin_context()
now = utils.utcnow()
now = timeutils.utcnow()
services = db.service_get_all(ctxt)
if host:
services = [s for s in services if s['host'] == host]
@ -1083,7 +1084,7 @@ class HostCommands(object):
print "%-25s\t%-15s" % (_('host'),
_('zone'))
ctxt = context.get_admin_context()
now = utils.utcnow()
now = timeutils.utcnow()
services = db.service_get_all(ctxt)
if zone:
services = [s for s in services if s['availability_zone'] == zone]

View File

@ -18,7 +18,7 @@
"""Super simple fake memcache client."""
from nova import utils
from nova.openstack.common import timeutils
class Client(object):
@ -35,7 +35,7 @@ class Client(object):
for k in self.cache.keys():
(timeout, _value) = self.cache[k]
if timeout and utils.utcnow_ts() >= timeout:
if timeout and timeutils.utcnow_ts() >= timeout:
del self.cache[k]
return self.cache.get(key, (0, None))[1]
@ -44,7 +44,7 @@ class Client(object):
"""Sets the value for a key."""
timeout = 0
if time != 0:
timeout = utils.utcnow_ts() + time
timeout = timeutils.utcnow_ts() + time
self.cache[key] = (timeout, value)
return True

View File

@ -28,6 +28,7 @@ from nova import network
from nova.network import model as network_model
from nova.notifier import api as notifier_api
from nova.openstack.common import cfg
from nova.openstack.common import timeutils
from nova import utils
LOG = log.getLogger(__name__)
@ -140,7 +141,7 @@ def audit_period_bounds(current_period=False):
begin, end = utils.last_completed_audit_period()
if current_period:
audit_start = end
audit_end = utils.utcnow()
audit_end = timeutils.utcnow()
else:
audit_start = begin
audit_end = end

View File

@ -21,7 +21,7 @@ from nova import log as logging
from nova.openstack.common import cfg
from nova.openstack.common import importutils
from nova.openstack.common import jsonutils
from nova import utils
from nova.openstack.common import timeutils
LOG = logging.getLogger(__name__)
@ -110,7 +110,7 @@ def notify(context, publisher_id, event_type, priority, payload):
{'message_id': str(uuid.uuid4()),
'publisher_id': 'compute.host1',
'timestamp': utils.utcnow(),
'timestamp': timeutils.utcnow(),
'priority': 'WARN',
'event_type': 'compute.create_instance',
'payload': {'instance_id': 12, ... }}
@ -129,7 +129,7 @@ def notify(context, publisher_id, event_type, priority, payload):
event_type=event_type,
priority=priority,
payload=payload,
timestamp=str(utils.utcnow()))
timestamp=str(timeutils.utcnow()))
try:
driver.notify(context, msg)
except Exception, e:

View File

@ -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

View File

@ -26,7 +26,7 @@ from nova import flags
from nova import log as logging
from nova.openstack.common import cfg
from nova.openstack.common import importutils
from nova import utils
from nova.openstack.common import timeutils
LOG = logging.getLogger(__name__)
@ -318,7 +318,7 @@ class DbQuotaDriver(object):
if isinstance(expire, (int, long)):
expire = datetime.timedelta(seconds=expire)
if isinstance(expire, datetime.timedelta):
expire = utils.utcnow() + expire
expire = timeutils.utcnow() + expire
if not isinstance(expire, datetime.datetime):
raise exception.InvalidReservationExpiration(expire=expire)

View File

@ -33,6 +33,7 @@ from nova import notifications
from nova.openstack.common import cfg
from nova.openstack.common import importutils
from nova.openstack.common import jsonutils
from nova.openstack.common import timeutils
from nova import rpc
from nova import utils
@ -58,7 +59,7 @@ def cast_to_volume_host(context, host, method, update_db=True, **kwargs):
if update_db:
volume_id = kwargs.get('volume_id', None)
if volume_id is not None:
now = utils.utcnow()
now = timeutils.utcnow()
db.volume_update(context, volume_id,
{'host': host, 'scheduled_at': now})
rpc.cast(context,
@ -75,7 +76,7 @@ def cast_to_compute_host(context, host, method, update_db=True, **kwargs):
instance_id = kwargs.get('instance_id', None)
instance_uuid = kwargs.get('instance_uuid', instance_id)
if instance_uuid is not None:
now = utils.utcnow()
now = timeutils.utcnow()
db.instance_update(context, instance_uuid,
{'host': host, 'scheduled_at': now})
rpc.cast(context,

View File

@ -25,8 +25,8 @@ from nova import exception
from nova import flags
from nova import log as logging
from nova.openstack.common import cfg
from nova.openstack.common import timeutils
from nova.scheduler import filters
from nova import utils
host_manager_opts = [
@ -274,7 +274,7 @@ class HostManager(object):
service_caps = self.service_states.get(host, {})
# Copy the capabilities, so we don't modify the original dict
capab_copy = dict(capabilities)
capab_copy["timestamp"] = utils.utcnow() # Reported time
capab_copy["timestamp"] = timeutils.utcnow() # Reported time
service_caps[service_name] = capab_copy
self.service_states[host] = service_caps
@ -282,7 +282,7 @@ class HostManager(object):
"""Check if host service capabilites are not recent enough."""
allowed_time_diff = FLAGS.periodic_interval * 3
caps = self.service_states[host][service]
if ((utils.utcnow() - caps["timestamp"]) <=
if ((timeutils.utcnow() - caps["timestamp"]) <=
datetime.timedelta(seconds=allowed_time_diff)):
return False
return True

View File

@ -29,7 +29,7 @@ import os
from nova import flags
from nova import log as logging
from nova.openstack.common import cfg
from nova import utils
from nova.openstack.common import timeutils
scheduler_json_config_location_opt = cfg.StrOpt(
@ -81,7 +81,7 @@ class SchedulerOptions(object):
def _get_time_now(self):
"""Get current UTC. Broken out for testing."""
return utils.utcnow()
return timeutils.utcnow()
def get_configuration(self, filename=None):
"""Check the json file for changes and load it if needed."""

View File

@ -35,10 +35,10 @@ from nova import flags
import nova.image.fake
from nova import log as logging
from nova.openstack.common import cfg
from nova.openstack.common import timeutils
from nova import service
from nova import tests
from nova.tests import fake_flags
from nova import utils
from nova.virt import fake
@ -131,7 +131,7 @@ class TestCase(unittest.TestCase):
# NOTE(vish): We need a better method for creating fixtures for tests
# now that we have some required db setup for the system
# to work properly.
self.start = utils.utcnow()
self.start = timeutils.utcnow()
tests.reset_db()
# emulate some of the mox stuff, we can't use the metaclass

View File

@ -20,10 +20,10 @@ import datetime
from nova import db
from nova import exception
from nova.openstack.common import timeutils
from nova.scheduler import host_manager
from nova import test
from nova.tests.scheduler import fakes
from nova import utils
class ComputeFilterClass1(object):
@ -90,10 +90,10 @@ class HostManagerTestCase(test.TestCase):
def test_update_service_capabilities(self):
service_states = self.host_manager.service_states
self.assertDictMatch(service_states, {})
self.mox.StubOutWithMock(utils, 'utcnow')
utils.utcnow().AndReturn(31337)
utils.utcnow().AndReturn(31338)
utils.utcnow().AndReturn(31339)
self.mox.StubOutWithMock(timeutils, 'utcnow')
timeutils.utcnow().AndReturn(31337)
timeutils.utcnow().AndReturn(31338)
timeutils.utcnow().AndReturn(31339)
host1_compute_capabs = dict(free_memory=1234, host_memory=5678,
timestamp=1)
@ -138,10 +138,10 @@ class HostManagerTestCase(test.TestCase):
self.host_manager.service_states = service_states
self.mox.StubOutWithMock(utils, 'utcnow')
utils.utcnow().AndReturn(datetime.datetime.fromtimestamp(3020))
utils.utcnow().AndReturn(datetime.datetime.fromtimestamp(3020))
utils.utcnow().AndReturn(datetime.datetime.fromtimestamp(3020))
self.mox.StubOutWithMock(timeutils, 'utcnow')
timeutils.utcnow().AndReturn(datetime.datetime.fromtimestamp(3020))
timeutils.utcnow().AndReturn(datetime.datetime.fromtimestamp(3020))
timeutils.utcnow().AndReturn(datetime.datetime.fromtimestamp(3020))
self.mox.ReplayAll()
res1 = self.host_manager.host_service_caps_stale('host1', 'compute')

View File

@ -28,6 +28,7 @@ from nova import db
from nova import exception
from nova import flags
from nova.openstack.common import jsonutils
from nova.openstack.common import timeutils
from nova import rpc
from nova.rpc import common as rpc_common
from nova.scheduler import driver
@ -983,12 +984,12 @@ class SchedulerDriverModuleTestCase(test.TestCase):
'extra_arg': 'meow'}
queue = 'fake_queue'
self.mox.StubOutWithMock(utils, 'utcnow')
self.mox.StubOutWithMock(timeutils, 'utcnow')
self.mox.StubOutWithMock(db, 'volume_update')
self.mox.StubOutWithMock(rpc, 'queue_get_for')
self.mox.StubOutWithMock(rpc, 'cast')
utils.utcnow().AndReturn('fake-now')
timeutils.utcnow().AndReturn('fake-now')
db.volume_update(self.context, 31337,
{'host': host, 'scheduled_at': 'fake-now'})
rpc.queue_get_for(self.context, 'volume', host).AndReturn(queue)
@ -1043,12 +1044,12 @@ class SchedulerDriverModuleTestCase(test.TestCase):
'extra_arg': 'meow'}
queue = 'fake_queue'
self.mox.StubOutWithMock(utils, 'utcnow')
self.mox.StubOutWithMock(timeutils, 'utcnow')
self.mox.StubOutWithMock(db, 'instance_update')
self.mox.StubOutWithMock(rpc, 'queue_get_for')
self.mox.StubOutWithMock(rpc, 'cast')
utils.utcnow().AndReturn('fake-now')
timeutils.utcnow().AndReturn('fake-now')
db.instance_update(self.context, 31337,
{'host': host, 'scheduled_at': 'fake-now'})
rpc.queue_get_for(self.context, 'compute', host).AndReturn(queue)

View File

@ -35,8 +35,8 @@ from nova import block_device
from nova import context
from nova import exception
from nova import flags
from nova.openstack.common import timeutils
from nova import test
from nova import utils
FLAGS = flags.FLAGS
@ -252,12 +252,12 @@ class ApiEc2TestCase(test.TestCase):
"""
conv = apirequest._database_to_isoformat
# sqlite database representation with microseconds
time_to_convert = utils.parse_strtime("2011-02-21 20:14:10.634276",
"%Y-%m-%d %H:%M:%S.%f")
time_to_convert = timeutils.parse_strtime("2011-02-21 20:14:10.634276",
"%Y-%m-%d %H:%M:%S.%f")
self.assertEqual(conv(time_to_convert), '2011-02-21T20:14:10.634Z')
# mysqlite database representation
time_to_convert = utils.parse_strtime("2011-02-21 19:56:18",
"%Y-%m-%d %H:%M:%S")
time_to_convert = timeutils.parse_strtime("2011-02-21 19:56:18",
"%Y-%m-%d %H:%M:%S")
self.assertEqual(conv(time_to_convert), '2011-02-21T19:56:18.000Z')
def test_xmlns_version_matches_request_version(self):

View File

@ -24,6 +24,7 @@ from nova import context
from nova import db
from nova import exception
from nova import flags
from nova.openstack.common import timeutils
from nova import test
from nova import utils
@ -96,7 +97,7 @@ class DbApiTestCase(test.TestCase):
db.migration_update(ctxt, migration.id, {"status": "CONFIRMED"})
# Ensure the new migration is not returned.
updated_at = utils.utcnow()
updated_at = timeutils.utcnow()
values = {"status": "finished", "updated_at": updated_at}
migration = db.migration_create(ctxt, values)
results = db.migration_get_all_unconfirmed(ctxt, 10)
@ -120,7 +121,7 @@ class DbApiTestCase(test.TestCase):
db.instance_update(ctxt, instance['uuid'], {"task_state": None})
# Ensure the newly rebooted instance is not returned.
updated_at = utils.utcnow()
updated_at = timeutils.utcnow()
values = {"task_state": "rebooting", "updated_at": updated_at}
instance = db.instance_create(ctxt, values)
results = db.instance_get_all_hung_in_rebooting(ctxt, 10)
@ -383,7 +384,7 @@ class DbApiTestCase(test.TestCase):
db.fixed_ip_create(ctxt, values)
def test_fixed_ip_disassociate_all_by_timeout_single_host(self):
now = utils.utcnow()
now = timeutils.utcnow()
ctxt = context.get_admin_context()
self._timeout_test(ctxt, now, False)
result = db.fixed_ip_disassociate_all_by_timeout(ctxt, 'foo', now)
@ -392,7 +393,7 @@ class DbApiTestCase(test.TestCase):
self.assertEqual(result, 1)
def test_fixed_ip_disassociate_all_by_timeout_multi_host(self):
now = utils.utcnow()
now = timeutils.utcnow()
ctxt = context.get_admin_context()
self._timeout_test(ctxt, now, True)
result = db.fixed_ip_disassociate_all_by_timeout(ctxt, 'foo', now)

View File

@ -31,13 +31,13 @@ from nova import exception
from nova import flags
from nova import log as logging
from nova.openstack.common import importutils
from nova.openstack.common import timeutils
from nova import test
from nova.tests.db import fakes as db_fakes
from nova.tests import fake_network
from nova.tests import fake_utils
from nova.tests.glance import stubs as glance_stubs
from nova.tests.xenapi import stubs
from nova import utils
from nova.virt.xenapi import connection as xenapi_conn
from nova.virt.xenapi import fake as xenapi_fake
from nova.virt.xenapi import vm_utils
@ -1316,7 +1316,8 @@ class XenAPIBWUsageTestCase(test.TestCase):
self.name = "instance-0001"
self.uuid = "1-2-3-4-5"
result = self.conn.get_all_bw_usage([testinstance()], utils.utcnow())
result = self.conn.get_all_bw_usage([testinstance()],
timeutils.utcnow())
self.assertEqual(result, [])

View File

@ -46,7 +46,6 @@ from eventlet import event
from eventlet.green import subprocess
from eventlet import greenthread
from eventlet import semaphore
import iso8601
import lockfile
import netaddr
@ -56,11 +55,10 @@ from nova import log as logging
from nova.openstack.common import cfg
from nova.openstack.common import excutils
from nova.openstack.common import importutils
from nova.openstack.common import timeutils
LOG = logging.getLogger(__name__)
ISO_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S"
PERFECT_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%f"
FLAGS = flags.FLAGS
FLAGS.register_opt(
@ -331,7 +329,7 @@ def last_completed_audit_period(unit=None):
unit, offset = unit.split("@", 1)
offset = int(offset)
rightnow = utcnow()
rightnow = timeutils.utcnow()
if unit not in ('month', 'day', 'year', 'hour'):
raise ValueError('Time period must be hour, day, month or year')
if unit == 'month':
@ -446,83 +444,6 @@ def get_my_linklocal(interface):
raise exception.NovaException(msg)
def utcnow():
"""Overridable version of utils.utcnow."""
if utcnow.override_time:
return utcnow.override_time
return datetime.datetime.utcnow()
utcnow.override_time = None
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 time.mktime(utcnow().timetuple())
def set_time_override(override_time=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
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 isotime(at=None):
"""Stringify time in ISO 8601 format"""
if not at:
at = 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
def parse_isotime(timestr):
"""Turn an iso formatted time back into a datetime."""
try:
return iso8601.parse_date(timestr)
except (iso8601.ParseError, 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 parse_mailmap(mailmap='.mailmap'):
mapping = {}
if os.path.exists(mailmap):
@ -1241,7 +1162,7 @@ def service_is_up(service):
"""Check whether a service is up based on last heartbeat."""
last_heartbeat = service['updated_at'] or service['created_at']
# Timestamps in DB are UTC.
elapsed = total_seconds(utcnow() - last_heartbeat)
elapsed = total_seconds(timeutils.utcnow() - last_heartbeat)
return abs(elapsed) <= FLAGS.service_down_time

View File

@ -1,7 +1,7 @@
[DEFAULT]
# The list of modules to copy from openstack-common
modules=cfg,excutils,local,importutils,iniparser,jsonutils,setup,policy
modules=cfg,excutils,importutils,iniparser,jsonutils,local,policy,setup,timeutils
# The base module to hold the copy of openstack.common
base=nova