From 827fbd01c306ce292e46b0d881bc3cc804202285 Mon Sep 17 00:00:00 2001 From: Pierre Riteau Date: Fri, 24 Feb 2023 05:34:07 +0100 Subject: [PATCH] Normalise format of OVN agent heartbeat timestamp A recent change [1] to show the real heartbeat timestamp from OVN agents had a side effect of changing the timestamp format, which now includes a timezone: +-------------------+----------------------------------+ | Field | Value | +-------------------+----------------------------------+ | last_heartbeat_at | 2023-02-23 14:12:07.471000+00:00 | +-------------------+----------------------------------+ This unexpected format change causes some clients to fail to parse the response to GET /v2.0/agents. Normalise the format of the timestamp to remove timezone information. Also remove the microsecond part, which was not done for OVN, but is absent from other network agents. [1] https://review.opendev.org/c/openstack/neutron/+/844179 Closes-Bug: #2008257 Change-Id: I75a37fb9b49a421e4524da6b56ef8362ceb6107b --- .../ml2/drivers/ovn/agent/neutron_agent.py | 3 ++- .../drivers/ovn/mech_driver/test_mech_driver.py | 2 +- .../ml2/drivers/ovn/agent/test_neutron_agent.py | 17 +++++++++++++++++ ...tbeat-timestamp-format-dcf80badbe267c68.yaml | 6 ++++++ 4 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 releasenotes/notes/fix-ovn-agent-heartbeat-timestamp-format-dcf80badbe267c68.yaml diff --git a/neutron/plugins/ml2/drivers/ovn/agent/neutron_agent.py b/neutron/plugins/ml2/drivers/ovn/agent/neutron_agent.py index 61f8ded970a..222c9e9cce8 100644 --- a/neutron/plugins/ml2/drivers/ovn/agent/neutron_agent.py +++ b/neutron/plugins/ml2/drivers/ovn/agent/neutron_agent.py @@ -81,7 +81,8 @@ class NeutronAgent(abc.ABC): return { 'binary': self.binary, 'host': self.chassis.hostname, - 'heartbeat_timestamp': self.updated_at, + 'heartbeat_timestamp': timeutils.normalize_time( + self.updated_at.replace(microsecond=0)), 'availability_zone': ', '.join( ovn_utils.get_chassis_availability_zones(self.chassis)), 'topic': 'n/a', diff --git a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py index b7cb07735ce..18f3f0d554a 100644 --- a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py +++ b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py @@ -1148,7 +1148,7 @@ class TestAgentApi(base.TestOVNFunctionalBase): 'Chassis_Private', self.chassis, 'nb_cfg_timestamp' ).execute(check_error=True) updated_at = datetime.datetime.fromtimestamp( - int(chassis_ts / 1000), datetime.timezone.utc) + int(chassis_ts / 1000)) # if table Chassis_Private present, agent.updated_at is # Chassis_Private.nb_cfg_timestamp self.assertEqual(updated_at, heartbeat_timestamp) diff --git a/neutron/tests/unit/plugins/ml2/drivers/ovn/agent/test_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/ovn/agent/test_neutron_agent.py index cd92c937534..9f92a65ff07 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/ovn/agent/test_neutron_agent.py +++ b/neutron/tests/unit/plugins/ml2/drivers/ovn/agent/test_neutron_agent.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime from unittest import mock import eventlet @@ -67,3 +68,19 @@ class AgentCacheTestCase(base.BaseTestCase): agents = list(agents) self.assertEqual(1, len(agents)) self.assertEqual('chassis5', agents[0].agent_id) + + @mock.patch.object(neutron_agent.ControllerAgent, 'alive') + def test_heartbeat_timestamp_format(self, agent_alive): + chassis_private = fakes.FakeOvsdbRow.create_one_ovsdb_row( + attrs={'name': 'chassis5'}) + agents = self.agent_cache.agents_by_chassis_private(chassis_private) + agent = list(agents)[0] + agent.chassis.hostname = 'fake-hostname' + agent.updated_at = datetime.datetime( + year=2023, month=2, day=23, hour=1, minute=2, second=3, + microsecond=456789).replace(tzinfo=datetime.timezone.utc) + agent_alive.return_value = True + + # Verify that both microseconds and timezone are dropped + self.assertEqual(str(agent.as_dict()['heartbeat_timestamp']), + '2023-02-23 01:02:03') diff --git a/releasenotes/notes/fix-ovn-agent-heartbeat-timestamp-format-dcf80badbe267c68.yaml b/releasenotes/notes/fix-ovn-agent-heartbeat-timestamp-format-dcf80badbe267c68.yaml new file mode 100644 index 00000000000..0f806e7b8a5 --- /dev/null +++ b/releasenotes/notes/fix-ovn-agent-heartbeat-timestamp-format-dcf80badbe267c68.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Normalise OVN agent heartbeat timestamp format to match other agent types. + This fixes parsing of ``GET /v2.0/agents`` for some clients, such as + gophercloud.