From 7396b8b1c8f38c5e73be036acee29851a3df1ca4 Mon Sep 17 00:00:00 2001 From: Frode Nordahl Date: Tue, 22 Aug 2023 12:03:40 +0200 Subject: [PATCH] Make version pinning optional The OVN charms prepared for the upgrade from OVN 20.03 to newer versions by enabling the version pinning by default. Since then we have reached agreement with upstream that rolling upgrades should work when upgrading within the previous upstream LTS version and the next. Having the pinning enabled by default causes unnecessary grief for anyone already upgraded to OVN 22.03, so it's time to turn it off by default. We add a charm configuration option in case anyone wants to upgrade across LTS boundaries in the future. Closes-Bug: #2030944 Signed-off-by: Frode Nordahl (cherry picked from commit f68ecbd10d2109014c67100ec7e7fe8e1823a7ec) (cherry picked from commit 2a61104364a5e0c5b241a514f65b2323475ed96e) Conflicts: config.yaml unit_tests/test_lib_charms_ovn_charm.py --- config.yaml | 15 +++++++++ lib/charms/ovn_charm.py | 3 +- unit_tests/test_lib_charms_ovn_charm.py | 43 ++++++++++++++++++++++--- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/config.yaml b/config.yaml index 8c80ace..982d0f0 100644 --- a/config.yaml +++ b/config.yaml @@ -348,4 +348,19 @@ options: should not normally happen with DPUs that only have one chip exposed. . Examples: [{"bus": "pci", "vendor_id": "15b3", "product_id": "a2d6" }, + enable-version-pinning: + type: boolean + default: true + description: | + OVN is a distributed system, and special consideration must be given to + the process used to upgrade OVN. + + In order to successfully perform a rolling upgrade, the ovn-controller + process needs to understand the structure of the database for the version + you are upgrading from and to simultaneously. + + Rolling upgrades are supported as long as the span of versions used in + the system is within the previous and the next upstream OVN LTS version. + If you are upgrading across LTS boundaries you may need to use version + pinning to avoid data plane outage during the upgrade. diff --git a/lib/charms/ovn_charm.py b/lib/charms/ovn_charm.py index 7433653..b7f8e63 100644 --- a/lib/charms/ovn_charm.py +++ b/lib/charms/ovn_charm.py @@ -1108,7 +1108,8 @@ def configure_ovs(self, sb_conn, mlockall_changed): 'external-ids:system-id={}' .format(self.get_ovs_hostname()), 'external-ids:ovn-remote={}'.format(sb_conn), - 'external_ids:ovn-match-northd-version=true', + 'external_ids:ovn-match-northd-version={}' + .format(self.options.enable_version_pinning), ): cmd = cmd + ('--', 'set', 'open-vswitch', '.', ovs_ext_id) self.run(*cmd) diff --git a/unit_tests/test_lib_charms_ovn_charm.py b/unit_tests/test_lib_charms_ovn_charm.py index a8c98d5..01d9c86 100644 --- a/unit_tests/test_lib_charms_ovn_charm.py +++ b/unit_tests/test_lib_charms_ovn_charm.py @@ -1084,7 +1084,7 @@ def test_configure_sources(self): class TestOVNChassisCharm(Helper): def setUp(self): - super().setUp(config={ + self.local_config = { 'enable-hardware-offload': False, 'enable-sriov': False, 'enable-dpdk': False, @@ -1096,7 +1096,9 @@ def setUp(self): 'vpd-device-spec': '[{"bus": "pci", "vendor_id": "beef", "device_id": "cafe"}]', 'ovn-source': 'distro', - }) + 'enable-version-pinning': False, + } + super().setUp(config=self.local_config) def test_optional_openstack_metadata(self): self.assertEquals(self.target.packages, ['ovn-host']) @@ -1232,7 +1234,7 @@ def test_configure_ovs(self): '--', 'set', 'open-vswitch', '.', 'external-ids:ovn-remote=fake-sb-conn-str', '--', 'set', 'open-vswitch', '.', - 'external_ids:ovn-match-northd-version=true', + 'external_ids:ovn-match-northd-version=False', ), ]) self.service_restart.assert_not_called() @@ -1258,7 +1260,7 @@ def test_configure_ovs(self): '--', 'set', 'open-vswitch', '.', 'external-ids:ovn-remote=fake-sb-conn-str', '--', 'set', 'open-vswitch', '.', - 'external_ids:ovn-match-northd-version=true', + 'external_ids:ovn-match-northd-version=False', ), mock.call('ovs-vsctl', '--id', '@manager', 'create', 'Manager', 'target="ptcp:6640:127.0.0.1"', @@ -1267,6 +1269,39 @@ def test_configure_ovs(self): ]) assert self.service_restart.called + def test_configure_ovs_version_pinning(self): + self.local_config.update({'enable-version-pinning': True}) + self.target = ovn_charm.BaseOVNChassisCharm() + self.patch_target('run') + self.patch_object(ovn_charm.OVNConfigurationAdapter, 'ovn_key') + self.patch_object(ovn_charm.OVNConfigurationAdapter, 'ovn_cert') + self.patch_object(ovn_charm.OVNConfigurationAdapter, 'ovn_ca_cert') + self.patch_object(ovn_charm.ch_core.host, 'service_restart') + self.patch_target('get_data_ip') + self.get_data_ip.return_value = 'fake-data-ip' + self.patch_target('get_ovs_hostname') + self.get_ovs_hostname.return_value = 'fake-ovs-hostname' + self.patch_target('check_if_paused') + self.check_if_paused.return_value = (None, None) + self.target.configure_ovs('fake-sb-conn-str', False) + self.run.assert_has_calls([ + mock.call('ovs-vsctl', '--no-wait', 'set-ssl', + mock.ANY, mock.ANY, mock.ANY), + mock.call( + 'ovs-vsctl', + '--', 'set', 'open-vswitch', '.', + 'external-ids:ovn-encap-type=geneve', + '--', 'set', 'open-vswitch', '.', + 'external-ids:ovn-encap-ip=fake-data-ip', + '--', 'set', 'open-vswitch', '.', + 'external-ids:system-id=fake-ovs-hostname', + '--', 'set', 'open-vswitch', '.', + 'external-ids:ovn-remote=fake-sb-conn-str', + '--', 'set', 'open-vswitch', '.', + 'external_ids:ovn-match-northd-version=True', + ), + ]) + def test_render_nrpe(self): self.patch_object(ovn_charm.nrpe, 'NRPE') self.patch_object(ovn_charm.nrpe, 'add_init_service_checks')