Round the elapsed time to the nearest second

The db truncates the microseconds so this can end up being negative.

Closes-Bug: #1493166

Change-Id: I5169821e7465e483b8379ee7f614ca08877973e7
This commit is contained in:
Angus Salkeld 2015-09-08 14:03:44 +10:00 committed by Sergey Kraynev
parent 69e44dbb17
commit 0bc4de65e3
4 changed files with 41 additions and 2 deletions

View File

@ -15,6 +15,7 @@
Utilities for handling ISO 8601 duration format.
"""
import datetime
import random
import re
import time
@ -80,3 +81,12 @@ def retry_backoff_delay(attempt, scale_factor=1.0, jitter_max=0.0):
if jitter_max == 0.0:
return exp
return exp + random.random() * jitter_max
def round_to_seconds(dt):
"""Round a datetime to the nearest second."""
rounding = 0
if dt.microsecond >= 500000:
rounding = 1
return dt + datetime.timedelta(0, rounding,
-dt.microsecond)

View File

@ -33,6 +33,7 @@ from heat.common.i18n import _LI
from heat.common.i18n import _LW
from heat.common import identifier
from heat.common import lifecycle_plugin_utils
from heat.common import timeutils
from heat.engine import dependencies
from heat.engine import environment
from heat.engine import event
@ -1688,8 +1689,10 @@ class Stack(collections.Mapping):
'''
Time elapsed in seconds since the stack operation started.
'''
start_time = self.updated_time or self.created_time
return (datetime.datetime.utcnow() - start_time).seconds
start_time = timeutils.round_to_seconds(self.updated_time or
self.created_time)
nowish = timeutils.round_to_seconds(datetime.datetime.utcnow())
return (nowish - start_time).seconds
def time_remaining(self):
'''

View File

@ -111,6 +111,17 @@ class StackTest(common.HeatTestCase):
10, 10, 0)
self.assertEqual(600, self.stack.time_elapsed())
@mock.patch.object(stack, 'datetime')
def test_time_elapsed_ms(self, mock_dt):
self.stack = stack.Stack(self.ctx, 'test_stack', self.tmpl)
# dummy create time 10:00:00
self.stack.created_time = datetime.datetime(2015, 7, 27, 10, 5, 0)
# mock utcnow set to microsecond offset
mock_dt.datetime.utcnow.return_value = datetime.datetime(2015, 7, 27,
10, 4, 59,
750000)
self.assertEqual(0, self.stack.time_elapsed())
@mock.patch.object(stack, 'datetime')
def test_time_elapsed_with_updated_time(self, mock_dt):
self.stack = stack.Stack(self.ctx, 'test_stack', self.tmpl)

View File

@ -11,6 +11,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import datetime
from testtools import matchers
from heat.common import timeutils as util
@ -157,3 +158,17 @@ class RetryBackoffJitterTest(common.HeatTestCase):
self.attempt, self.scale_factor, self.jitter_max)
self.assertThat(delay, matchers.GreaterThan(self.delay_from))
self.assertThat(delay, matchers.LessThan(self.delay_to))
class RoundToSecondsTest(common.HeatTestCase):
scenarios = [('down', dict(in_secs=5, in_ms=12345, out_secs=5)),
('up', dict(in_secs=5, in_ms=501000, out_secs=6)),
('same', dict(in_secs=5, in_ms=0, out_secs=5))]
def test_rounding(self):
inp = datetime.datetime(2015, 7, 27, 4,
34, self.in_secs, self.in_ms)
exp = datetime.datetime(2015, 7, 27, 4,
34, self.out_secs, 0)
self.assertEqual(exp, util.round_to_seconds(inp))