Skip to content

Commit b57f96c

Browse files
authored
Merge pull request #153 from stackhpc/upstream/2023.1-2024-06-24
Synchronise 2023.1 with upstream
2 parents 5430119 + 0a7b9d3 commit b57f96c

File tree

6 files changed

+83
-2
lines changed

6 files changed

+83
-2
lines changed

neutron/common/ovn/constants.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@
213213
'wpad',
214214
'tftp_server']
215215

216+
OVN_MAP_TYPE_DHCP_OPTS = [
217+
'classless_static_route',
218+
]
219+
216220
# Special option for disabling DHCP via extra DHCP options
217221
DHCP_DISABLED_OPT = 'dhcp_disabled'
218222

neutron/common/ovn/utils.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,10 @@ def is_dhcp_option_quoted(opt_value):
249249
return opt_value.startswith('"') and opt_value.endswith('"')
250250

251251

252+
def is_dhcp_option_a_map(opt_value):
253+
return opt_value.startswith('{') and opt_value.endswith('}')
254+
255+
252256
def get_lsp_dhcp_opts(port, ip_version):
253257
# Get dhcp options from Neutron port, for setting DHCP_Options row
254258
# in OVN.
@@ -287,6 +291,9 @@ def get_lsp_dhcp_opts(port, ip_version):
287291
if (opt in constants.OVN_STR_TYPE_DHCP_OPTS and
288292
not is_dhcp_option_quoted(edo['opt_value'])):
289293
edo['opt_value'] = '"%s"' % edo['opt_value']
294+
elif (opt in constants.OVN_MAP_TYPE_DHCP_OPTS and
295+
not is_dhcp_option_a_map(edo['opt_value'])):
296+
edo['opt_value'] = '{%s}' % edo['opt_value']
290297
lsp_dhcp_opts[opt] = edo['opt_value']
291298

292299
return (lsp_dhcp_disabled, lsp_dhcp_opts)

neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,18 @@ def _get_subnet_dhcp_options_for_port(self, port, ip_version):
191191
return opts
192192
return get_opts[0]
193193

194+
def _merge_map_dhcp_option(self, opt, port_opts, subnet_opts):
195+
"""Merge a port and subnet map DHCP option.
196+
197+
If a DHCP option exists in both port and subnet, the port
198+
should inherit the values from the subnet.
199+
"""
200+
port_opt = port_opts[opt]
201+
subnet_opt = subnet_opts.get(opt)
202+
if not subnet_opt:
203+
return port_opt
204+
return '{%s, %s}' % (subnet_opt[1:-1], port_opt[1:-1])
205+
194206
def _get_port_dhcp_options(self, port, ip_version):
195207
"""Return dhcp options for port.
196208
@@ -223,6 +235,12 @@ def _get_port_dhcp_options(self, port, ip_version):
223235
if not lsp_dhcp_opts:
224236
return subnet_dhcp_options
225237

238+
# Check for map DHCP options
239+
for opt in ovn_const.OVN_MAP_TYPE_DHCP_OPTS:
240+
if opt in lsp_dhcp_opts:
241+
lsp_dhcp_opts[opt] = self._merge_map_dhcp_option(
242+
opt, lsp_dhcp_opts, subnet_dhcp_options['options'])
243+
226244
# This port has extra DHCP options defined, so we will create a new
227245
# row in DHCP_Options table for it.
228246
subnet_dhcp_options['options'].update(lsp_dhcp_opts)

neutron/tests/unit/common/ovn/test_utils.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,20 @@ def test_get_lsp_dhcp_opts_for_domain_search(self):
476476
expected_options = {'domain_search_list': '"openstack.org,ovn.org"'}
477477
self.assertEqual(expected_options, options)
478478

479+
def test_get_lsp_dhcp_opts_sanitize_map(self):
480+
opt = {'opt_name': 'classless-static-route',
481+
'opt_value': '128.128.128.128/32,22.2.0.2',
482+
'ip_version': 4}
483+
port = {portbindings.VNIC_TYPE: portbindings.VNIC_NORMAL,
484+
edo_ext.EXTRADHCPOPTS: [opt]}
485+
dhcp_disabled, options = utils.get_lsp_dhcp_opts(port, 4)
486+
self.assertFalse(dhcp_disabled)
487+
# Assert option got translated to "classless_static_route" and
488+
# the value is a map (wrapped with {})
489+
expected_options = {
490+
'classless_static_route': '{128.128.128.128/32,22.2.0.2}'}
491+
self.assertEqual(expected_options, options)
492+
479493

480494
class TestGetDhcpDnsServers(base.BaseTestCase):
481495

neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3942,6 +3942,44 @@ def test__get_subnet_dhcp_options_for_port_v6_dhcp_disabled(self):
39423942
self._test__get_subnet_dhcp_options_for_port(ip_version=6,
39433943
enable_dhcp=False)
39443944

3945+
def test_get_port_dhcp_options_classless_static_route(self):
3946+
port = {
3947+
'id': 'foo-port',
3948+
'device_owner': 'compute:None',
3949+
'fixed_ips': [{'subnet_id': 'foo-subnet',
3950+
'ip_address': '10.0.0.11'}],
3951+
'extra_dhcp_opts': [
3952+
{'ip_version': 4, 'opt_name': 'classless-static-route',
3953+
'opt_value': '128.128.128.128/32,22.2.0.2'}]}
3954+
3955+
self.mech_driver._ovn_client._get_subnet_dhcp_options_for_port = (
3956+
mock.Mock(
3957+
return_value=({
3958+
'cidr': '10.0.0.0/24',
3959+
'external_ids': {'subnet_id': 'foo-subnet'},
3960+
'options': {
3961+
'classless_static_route':
3962+
'{169.254.169.254/32,10.0.0.2}'},
3963+
'uuid': 'foo-uuid'})))
3964+
3965+
# Expect both the subnet and port classless_static_route
3966+
# to be merged
3967+
expected_routes = ('{169.254.169.254/32,10.0.0.2, '
3968+
'128.128.128.128/32,22.2.0.2}')
3969+
expected_dhcp_options = {
3970+
'cidr': '10.0.0.0/24',
3971+
'external_ids': {'subnet_id': 'foo-subnet',
3972+
'port_id': 'foo-port'},
3973+
'options': {'classless_static_route': expected_routes}
3974+
}
3975+
3976+
self.mech_driver.nb_ovn.add_dhcp_options.return_value = 'foo-val'
3977+
dhcp_options = self.mech_driver._ovn_client._get_port_dhcp_options(
3978+
port, 4)
3979+
self.assertEqual({'cmd': 'foo-val'}, dhcp_options)
3980+
self.mech_driver.nb_ovn.add_dhcp_options.assert_called_once_with(
3981+
'foo-subnet', port_id='foo-port', **expected_dhcp_options)
3982+
39453983

39463984
class TestOVNMechanismDriverSecurityGroup(MechDriverSetupBase,
39473985
test_security_group.Ml2SecurityGroupsTestCase):

tox.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ setenv = {[testenv:dsvm-functional]setenv}
7979
deps = {[testenv:dsvm-functional]deps}
8080
commands =
8181
bash {toxinidir}/tools/deploy_rootwrap.sh {toxinidir} {envdir}/etc {envdir}/bin
82-
stestr run --exclude-regex (.*MySQL\.|.*PostgreSQL\.|.*test_get_all_devices|.*BaseOVSTestCase\.) {posargs}
83-
stestr run --combine --concurrency 1 (.*MySQL\.|.*PostgreSQL\.|.*test_get_all_devices|.*BaseOVSTestCase\.) {posargs}
82+
stestr run --exclude-regex (.*MySQL\.|.*PostgreSQL\.|.*test_get_all_devices|.*BaseOVSTestCase\.|.*test_periodic_sync_routers_task) {posargs}
83+
stestr run --combine --concurrency 1 (.*MySQL\.|.*PostgreSQL\.|.*test_get_all_devices|.*BaseOVSTestCase\.|.*test_periodic_sync_routers_task) {posargs}
8484

8585
[testenv:dsvm-fullstack]
8686
setenv = {[testenv]setenv}

0 commit comments

Comments
 (0)