diff --git a/neutron/conf/plugins/ml2/drivers/ovn/ovn_conf.py b/neutron/conf/plugins/ml2/drivers/ovn/ovn_conf.py index ea5c1b55812..6c789571cfb 100644 --- a/neutron/conf/plugins/ml2/drivers/ovn/ovn_conf.py +++ b/neutron/conf/plugins/ml2/drivers/ovn/ovn_conf.py @@ -171,10 +171,11 @@ ovn_opts = [ "automatically set on each subnet upon creation and " "on all existing subnets when Neutron starts.\n" "An empty value for a DHCP option will cause that " - "option to be unset globally.\n" + "option to be unset globally. Multiple values should " + "be separated by semi-colon.\n" "EXAMPLES:\n" - "- ntp_server:1.2.3.4,wpad:1.2.3.5 - Set ntp_server " - "and wpad\n" + "- ntp_server:1.2.3.4,wpad:1.2.3.5;1.2.3.6 - Set " + "ntp_server and wpad\n" "- ntp_server:,wpad:1.2.3.5 - Unset ntp_server and " "set wpad\n" "See the ovn-nb(5) man page for available options.")), @@ -184,7 +185,8 @@ ovn_opts = [ "automatically set on each subnet upon creation and " "on all existing subnets when Neutron starts.\n" "An empty value for a DHCPv6 option will cause that " - "option to be unset globally.\n" + "option to be unset globally. Multiple values should " + "be separated by semi-colon.\n" "See the ovn-nb(5) man page for available options.")), cfg.BoolOpt('ovn_emit_need_to_frag', default=True, diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py index 0fe4b285115..0265c9768d1 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py @@ -2348,7 +2348,12 @@ class OVNClient: # If the value is null (i.e. config ntp_server:), treat it as # a request to remove the option if value: - options[option] = value + # Example: ntp_server='{1.2.3.4, 1.2.3.5}'. A single value is + # also allowed but in shake of readability, it is printed as a + # single string. + _value = value.split(';') + options[option] = (_value[0] if len(_value) == 1 else + '{%s}' % ', '.join(_value)) else: try: del options[option] diff --git a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_client.py b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_client.py index 8d9fa3ea999..5fe956f6490 100644 --- a/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_client.py +++ b/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovn_client.py @@ -452,3 +452,16 @@ class TestOVNClient(testlib_api.MySQLTestCaseMixin, port_data['id']) req.get_response(self.api) _check_bw(port_data['id'], max_kbps, max_burst_kbps, min_kbps) + + def test_create_subnet_with_dhcp_options(self): + cfg.CONF.set_override('ovn_dhcp4_global_options', + 'ntp_server:1.2.3.4;1.2.3.5,wpad:1.2.3.6', + group='ovn') + with self.network('test-ovn-client') as net: + with self.subnet(net): + dhcp_options = self.nb_api.dhcp_options_list().execute( + check_error=True)[0] + self.assertEqual('{1.2.3.4, 1.2.3.5}', + dhcp_options.options['ntp_server']) + self.assertEqual('1.2.3.6', + dhcp_options.options['wpad'])