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')