ovn: Always use UTC for Hash ring timestamps
When a node is created in ovn_hash_ring table, it used to use timestamp depending on the system or mysql timezone. This caused troubles for machines using western timezones when getting active nodes before the first liveness check, becaus the time difference between UTC and local time was always in hours and the limit is 30 seconds. This patch configures OVN Hash Ring model to always use UTC when creating a node so the times are always compared to UTC, regardless of the used timezone. Note that the created_at and updated_at are not user facing columns. Change-Id: I9172254ce9b1880833128bdcaacacb93821933dd Closes-bug: #1894117 Signed-off-by: Jakub Libosvar <libosvar@redhat.com>
This commit is contained in:
parent
5e942ff21a
commit
a84462f698
|
@ -54,7 +54,11 @@ class HashRingManager(object):
|
|||
nodes = db_hash_ring.get_active_nodes(
|
||||
self.admin_ctx,
|
||||
constants.HASH_RING_CACHE_TIMEOUT, self._group, from_host=True)
|
||||
dont_cache = nodes and nodes[0].created_at == nodes[0].updated_at
|
||||
# created_at and updated_at differ in microseonds so we compare their
|
||||
# difference is less than a second to be safe on slow machines
|
||||
dont_cache = nodes and (
|
||||
nodes[0].updated_at - nodes[0].created_at < datetime.timedelta(
|
||||
seconds=1))
|
||||
if not dont_cache:
|
||||
self._cache_startup_timeout = False
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# under the License.
|
||||
|
||||
from neutron_lib.db import model_base
|
||||
from oslo_utils import timeutils
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import sqlite
|
||||
|
||||
|
@ -51,9 +52,9 @@ class OVNHashRing(model_base.BASEV2):
|
|||
node_uuid = sa.Column(sa.String(36), nullable=False, index=True)
|
||||
group_name = sa.Column(sa.String(256), nullable=False, index=True)
|
||||
hostname = sa.Column(sa.String(256), nullable=False)
|
||||
created_at = sa.Column(sa.DateTime(), default=sa.func.now(),
|
||||
created_at = sa.Column(sa.DateTime(), default=timeutils.utcnow,
|
||||
nullable=False)
|
||||
updated_at = sa.Column(sa.DateTime(), default=sa.func.now(),
|
||||
updated_at = sa.Column(sa.DateTime(), default=timeutils.utcnow,
|
||||
nullable=False)
|
||||
__table_args__ = (
|
||||
sa.PrimaryKeyConstraint(
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# under the License.
|
||||
|
||||
import datetime
|
||||
import time
|
||||
from unittest import mock
|
||||
|
||||
from neutron_lib import context
|
||||
|
@ -118,6 +119,7 @@ class TestHashRingManager(testlib_api.SqlTestCaseLight):
|
|||
self.assertTrue(self.hash_ring_manager._cache_startup_timeout)
|
||||
|
||||
# Touch the nodes (== update the updated_at column)
|
||||
time.sleep(1)
|
||||
db_hash_ring.touch_nodes_from_host(
|
||||
self.admin_ctx, HASH_RING_TEST_GROUP)
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# under the License.
|
||||
|
||||
import datetime
|
||||
import time
|
||||
from unittest import mock
|
||||
|
||||
from neutron_lib import context
|
||||
|
@ -44,9 +45,13 @@ class TestHashRing(testlib_api.SqlTestCaseLight):
|
|||
def _get_node_row(self, node_uuid):
|
||||
try:
|
||||
with db_api.CONTEXT_WRITER.using(self.admin_ctx):
|
||||
return self.admin_ctx.session.query(
|
||||
node = self.admin_ctx.session.query(
|
||||
ovn_models.OVNHashRing).filter_by(
|
||||
node_uuid=node_uuid).one()
|
||||
# Ignore miliseconds
|
||||
node.created_at = node.created_at.replace(microsecond=0)
|
||||
node.updated_at = node.updated_at.replace(microsecond=0)
|
||||
return node
|
||||
except exc.NoResultFound:
|
||||
return
|
||||
|
||||
|
@ -97,6 +102,7 @@ class TestHashRing(testlib_api.SqlTestCaseLight):
|
|||
self.assertEqual(node_db.created_at, node_db.updated_at)
|
||||
|
||||
# Touch the nodes from our host
|
||||
time.sleep(1)
|
||||
ovn_hash_ring_db.touch_nodes_from_host(self.admin_ctx,
|
||||
HASH_RING_TEST_GROUP)
|
||||
|
||||
|
@ -123,6 +129,7 @@ class TestHashRing(testlib_api.SqlTestCaseLight):
|
|||
self.admin_ctx, interval=60, group_name=HASH_RING_TEST_GROUP)))
|
||||
|
||||
# Substract 60 seconds from utcnow() and touch the nodes from our host
|
||||
time.sleep(1)
|
||||
fake_utcnow = timeutils.utcnow() - datetime.timedelta(seconds=60)
|
||||
with mock.patch.object(timeutils, 'utcnow') as mock_utcnow:
|
||||
mock_utcnow.return_value = fake_utcnow
|
||||
|
@ -161,6 +168,7 @@ class TestHashRing(testlib_api.SqlTestCaseLight):
|
|||
self.assertEqual(node_db.created_at, node_db.updated_at)
|
||||
|
||||
# Touch one of the nodes
|
||||
time.sleep(1)
|
||||
ovn_hash_ring_db.touch_node(self.admin_ctx, nodes[0])
|
||||
|
||||
# Assert it has been updated
|
||||
|
@ -217,6 +225,7 @@ class TestHashRing(testlib_api.SqlTestCaseLight):
|
|||
self.assertEqual(node_db.created_at, node_db.updated_at)
|
||||
|
||||
# Touch the nodes from group1
|
||||
time.sleep(1)
|
||||
ovn_hash_ring_db.touch_nodes_from_host(self.admin_ctx,
|
||||
HASH_RING_TEST_GROUP)
|
||||
|
||||
|
|
Loading…
Reference in New Issue