Skip to content

Commit 46c3b2b

Browse files
authored
Merge branch 'stackhpc/yoga' into upstream/yoga-2022-12-26
2 parents 70f32b9 + 270f1da commit 46c3b2b

File tree

11 files changed

+280
-52
lines changed

11 files changed

+280
-52
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @stackhpc/openstack
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
name: Tag & Release
3+
'on':
4+
push:
5+
branches:
6+
- stackhpc/yoga
7+
permissions:
8+
contents: write
9+
jobs:
10+
tag-and-release:
11+
uses: stackhpc/.github/.github/workflows/tag-and-release.yml@main

doc/source/ovn/gaps.rst

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,25 @@ at [1]_.
3232
can announce host routes for both floating and fixed IP addresses. These
3333
functions are not supported in OVN.
3434

35-
* Baremetal provisioning with iPXE
35+
* Baremetal provisioning with iPXE without Neutron DHCP agent for IPv6
3636

37-
The core OVN DHCP server implementation does not have support for
38-
sending different boot options based on the ``gpxe`` DHCP Option
39-
(no. 175). Also, Ironic uses dnsmasq syntax when configuring the DHCP
40-
options for Neutron [2]_ which is not understood by the OVN driver.
37+
The core OVN built-in DHCP server implementation does not
38+
yet support PXE booting for IPv6. This can be achieved at
39+
the moment if used with the Neutron DHCP agent by deploying it
40+
on OVN gateway nodes and disabling the OVN DHCP by setting the
41+
``[ovn]/disable_ovn_dhcp_for_baremetal_ports`` configuration option
42+
to True.
4143

4244
* QoS minimum bandwidth allocation in Placement API
4345

4446
ML2/OVN integration with the Nova placement API to provide guaranteed
45-
minimum bandwidth for ports [3]_.
47+
minimum bandwidth for ports [4]_. Work in progress, see [5]_
4648

4749
* IPv6 Prefix Delegation
4850

4951
Currently ML2/OVN doesn't implement IPv6 prefix delegation. OVN logical
50-
routers have this capability implemented in [4]_ and we have an open RFE to
51-
fill this gap [5]_.
52+
routers have this capability implemented in [6]_ and we have an open RFE to
53+
fill this gap [7]_.
5254

5355
* East/West Fragmentation
5456

@@ -62,11 +64,12 @@ at [1]_.
6264
from instances to reach the DHCP agent. For OVN this traffic has to be explicitly
6365
allowed by security group rules attached to the instance. Note that the default
6466
security group does allow all outgoing traffic, so this only becomes relevant
65-
when using custom security groups [6]_.
67+
when using custom security groups [8]_. Proposed patch is [9]_ but it
68+
needs to be revived and updated.
6669

6770
* DNS resolution for instances
6871

69-
OVN cannot use the host's networking for DNS resolution, so Case 2b in [7]_ can
72+
OVN cannot use the host's networking for DNS resolution, so Case 2b in [10]_ can
7073
only be used when additional DHCP agents are deployed. For Case 2a a different
7174
configuration option has to be used in ``ml2_conf.ini``::
7275

@@ -82,11 +85,12 @@ References
8285
----------
8386

8487
.. [1] https://github.com/ovn-org/ovn/blob/master/TODO.rst
85-
.. [2] https://github.com/openstack/ironic/blob/123cb22c731f93d0c608d791b41e05884fe18c04/ironic/common/pxe_utils.py#L447-L462>
86-
.. [3] https://specs.openstack.org/openstack/neutron-specs/specs/rocky/minimum-bandwidth-allocation-placement-api.html
87-
.. [4] https://patchwork.ozlabs.org/project/openvswitch/patch/6aec0fb280f610a2083fbb6c61e251b1d237b21f.1576840560.git.lorenzo.bianconi@redhat.com/
88-
.. [5] https://bugs.launchpad.net/neutron/+bug/1895972
89-
.. [6] https://bugs.launchpad.net/neutron/+bug/1926515
90-
.. [7] https://docs.openstack.org/neutron/latest/admin/config-dns-res.html
91-
.. [8] https://bugs.launchpad.net/neutron/+bug/1951816
92-
.. [9] https://bugs.launchpad.net/neutron/+bug/1950686
88+
.. [2] https://bugzilla.redhat.com/show_bug.cgi?id=2060310
89+
.. [3] https://review.opendev.org/c/openstack/neutron/+/842292
90+
.. [4] https://specs.openstack.org/openstack/neutron-specs/specs/rocky/minimum-bandwidth-allocation-placement-api.html
91+
.. [5] https://review.opendev.org/c/openstack/neutron/+/786478
92+
.. [6] https://patchwork.ozlabs.org/project/openvswitch/patch/6aec0fb280f610a2083fbb6c61e251b1d237b21f.1576840560.git.lorenzo.bianconi@redhat.com/
93+
.. [7] https://bugs.launchpad.net/neutron/+bug/1895972
94+
.. [8] https://bugs.launchpad.net/neutron/+bug/1926515
95+
.. [9] https://review.opendev.org/c/openstack/neutron/+/788594
96+
.. [10] https://docs.openstack.org/neutron/latest/admin/config-dns-res.html

neutron/common/ovn/constants.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# under the License.
1212

1313
import collections
14+
import copy
1415
import re
1516
import uuid
1617

@@ -132,10 +133,11 @@
132133
'T1': 'T1',
133134
'T2': 'T2',
134135
'bootfile-name': 'bootfile_name',
136+
'bootfile-name-alt': 'bootfile_name_alt',
135137
'wpad': 'wpad',
136138
'path-prefix': 'path_prefix',
137139
'tftp-server-address': 'tftp_server_address',
138-
'server-ip-address': 'tftp_server_address',
140+
'server-ip-address': 'next_server',
139141
'1': 'netmask',
140142
'3': 'router',
141143
'6': 'dns_server',
@@ -177,11 +179,21 @@
177179
'23': 'dns_server'},
178180
}
179181

182+
# Baremetal specific DHCP options for VNIC_BAREMETAL ports
183+
SUPPORTED_BM_DHCP_OPTS_MAPPING = copy.deepcopy(
184+
SUPPORTED_DHCP_OPTS_MAPPING)
185+
SUPPORTED_BM_DHCP_OPTS_MAPPING[4].update({
186+
'tag:ipxe,bootfile-name': 'bootfile_name',
187+
'tag:ipxe,67': 'bootfile_name',
188+
'tag:!ipxe,bootfile-name': 'bootfile_name_alt',
189+
'tag:!ipxe,67': 'bootfile_name_alt'})
190+
180191
# OVN string type DHCP options
181192
OVN_STR_TYPE_DHCP_OPTS = [
182193
'domain_name',
183194
'domain_search_list',
184195
'bootfile_name',
196+
'bootfile_name_alt',
185197
'path_prefix',
186198
'wpad',
187199
'tftp_server']

neutron/common/ovn/utils.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,12 @@ def validate_port_extra_dhcp_opts(port):
203203
:param port: A neutron port.
204204
:returns: A PortExtraDHCPValidation object.
205205
"""
206+
# Get the right option mappings according to the port's vnic_type
207+
vnic_type = port.get(portbindings.VNIC_TYPE, portbindings.VNIC_NORMAL)
208+
mapping = constants.SUPPORTED_DHCP_OPTS_MAPPING
209+
if vnic_type == portbindings.VNIC_BAREMETAL:
210+
mapping = constants.SUPPORTED_BM_DHCP_OPTS_MAPPING
211+
206212
invalid = {const.IP_VERSION_4: [], const.IP_VERSION_6: []}
207213
failed = False
208214
for edo in port.get(edo_ext.EXTRADHCPOPTS, []):
@@ -215,7 +221,7 @@ def validate_port_extra_dhcp_opts(port):
215221
failed = False
216222
break
217223

218-
if opt_name not in constants.SUPPORTED_DHCP_OPTS_MAPPING[ip_version]:
224+
if opt_name not in mapping[ip_version]:
219225
invalid[ip_version].append(opt_name)
220226
failed = True
221227

@@ -235,14 +241,16 @@ def get_lsp_dhcp_opts(port, ip_version):
235241
lsp_dhcp_disabled = False
236242
lsp_dhcp_opts = {}
237243
vnic_type = port.get(portbindings.VNIC_TYPE, portbindings.VNIC_NORMAL)
244+
is_baremetal = vnic_type == portbindings.VNIC_BAREMETAL
238245

239-
# NOTE(lucasagomes): Baremetal does not yet work with OVN's built-in
240-
# DHCP server, disable it for now
241-
if (is_network_device_port(port) or
242-
vnic_type == portbindings.VNIC_BAREMETAL):
246+
if is_network_device_port(port):
247+
lsp_dhcp_disabled = True
248+
elif is_baremetal and ovn_conf.is_ovn_dhcp_disabled_for_baremetal():
243249
lsp_dhcp_disabled = True
244250
else:
245-
mapping = constants.SUPPORTED_DHCP_OPTS_MAPPING[ip_version]
251+
mapping = (constants.SUPPORTED_BM_DHCP_OPTS_MAPPING[ip_version]
252+
if is_baremetal else
253+
constants.SUPPORTED_DHCP_OPTS_MAPPING[ip_version])
246254
for edo in port.get(edo_ext.EXTRADHCPOPTS, []):
247255
if edo['ip_version'] != ip_version:
248256
continue

neutron/conf/plugins/ml2/drivers/ovn/ovn_conf.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,12 @@
197197
'or by checking the output of the following command: \n'
198198
'ovs-appctl -t ovs-vswitchd dpif/show-dp-features '
199199
'br-int | grep "Check pkt length action".')),
200+
cfg.BoolOpt('disable_ovn_dhcp_for_baremetal_ports',
201+
default=False,
202+
help=_('Disable OVN\'s built-in DHCP for baremetal ports '
203+
'(VNIC type "baremetal"). This alllow operators to '
204+
'plug their own DHCP server of choice for PXE booting '
205+
'baremetal nodes. Defaults to False.')),
200206
]
201207

202208

@@ -306,3 +312,7 @@ def is_ovn_emit_need_to_frag_enabled():
306312

307313
def is_igmp_snooping_enabled():
308314
return cfg.CONF.OVS.igmp_snooping_enable
315+
316+
317+
def is_ovn_dhcp_disabled_for_baremetal():
318+
return cfg.CONF.ovn.disable_ovn_dhcp_for_baremetal_ports

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

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
from futurist import periodics
2323
from neutron_lib.api.definitions import external_net
24+
from neutron_lib.api.definitions import portbindings
2425
from neutron_lib.api.definitions import provider_net as pnet
2526
from neutron_lib.api.definitions import segment as segment_def
2627
from neutron_lib import constants as n_const
@@ -888,6 +889,58 @@ def update_port_virtual_type(self):
888889
txn.add(cmd)
889890
raise periodics.NeverAgain()
890891

892+
# A static spacing value is used here, but this method will only run
893+
# once per lock due to the use of periodics.NeverAgain().
894+
@periodics.periodic(spacing=600, run_immediately=True)
895+
def check_baremetal_ports_dhcp_options(self):
896+
"""Update baremetal ports DHCP options
897+
898+
Update baremetal ports DHCP options based on the
899+
"disable_ovn_dhcp_for_baremetal_ports" configuration option.
900+
"""
901+
# If external ports is not supported stop running
902+
# this periodic task
903+
if not self._ovn_client.is_external_ports_supported():
904+
raise periodics.NeverAgain()
905+
906+
if not self.has_lock:
907+
return
908+
909+
context = n_context.get_admin_context()
910+
ports = self._ovn_client._plugin.get_ports(
911+
context,
912+
filters={portbindings.VNIC_TYPE: portbindings.VNIC_BAREMETAL})
913+
if not ports:
914+
raise periodics.NeverAgain()
915+
916+
with self._nb_idl.transaction(check_error=True) as txn:
917+
for port in ports:
918+
lsp = self._nb_idl.lsp_get(port['id']).execute(
919+
check_error=True)
920+
if not lsp:
921+
continue
922+
923+
update_dhcp = False
924+
if ovn_conf.is_ovn_dhcp_disabled_for_baremetal():
925+
if lsp.dhcpv4_options or lsp.dhcpv6_options:
926+
update_dhcp = True
927+
else:
928+
if not lsp.dhcpv4_options and not lsp.dhcpv6_options:
929+
update_dhcp = True
930+
931+
if update_dhcp:
932+
port_info = self._ovn_client._get_port_options(port)
933+
dhcpv4_options, dhcpv6_options = (
934+
self._ovn_client.update_port_dhcp_options(
935+
port_info, txn))
936+
txn.add(self._nb_idl.set_lswitch_port(
937+
lport_name=port['id'],
938+
dhcpv4_options=dhcpv4_options,
939+
dhcpv6_options=dhcpv6_options,
940+
if_exists=False))
941+
942+
raise periodics.NeverAgain()
943+
891944
# TODO(ralonsoh): Remove this in the Antelope+4 cycle
892945
@periodics.periodic(spacing=600, run_immediately=True)
893946
def create_router_extra_attributes_registers(self):
@@ -899,6 +952,7 @@ def create_router_extra_attributes_registers(self):
899952
only execution method finds those ``Routers`` registers without the
900953
child one and creates one with the default values.
901954
"""
955+
902956
if not self.has_lock:
903957
return
904958

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

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,28 @@ def sync_ha_chassis_group(self, context, network_id, txn):
512512

513513
return ha_ch_grp.uuid
514514

515+
def update_port_dhcp_options(self, port_info, txn):
516+
dhcpv4_options = []
517+
dhcpv6_options = []
518+
if not port_info.dhcpv4_options:
519+
dhcpv4_options = []
520+
elif 'cmd' in port_info.dhcpv4_options:
521+
dhcpv4_options = txn.add(port_info.dhcpv4_options['cmd'])
522+
else:
523+
dhcpv4_options = [port_info.dhcpv4_options['uuid']]
524+
if not port_info.dhcpv6_options:
525+
dhcpv6_options = []
526+
elif 'cmd' in port_info.dhcpv6_options:
527+
dhcpv6_options = txn.add(port_info.dhcpv6_options['cmd'])
528+
else:
529+
dhcpv6_options = [port_info.dhcpv6_options['uuid']]
530+
531+
return (dhcpv4_options, dhcpv6_options)
532+
533+
def create_port(self, context, port):
534+
if utils.is_lsp_ignored(port):
535+
return
536+
515537
def get_external_ids_from_port(self, port):
516538
port_info = self._get_port_options(port)
517539
external_ids = {ovn_const.OVN_PORT_NAME_EXT_ID_KEY: port['name'],
@@ -550,18 +572,8 @@ def create_port(self, context, port):
550572
'Logical_Switch', 'name', lswitch_name)
551573

552574
with self._nb_idl.transaction(check_error=True) as txn:
553-
if not port_info.dhcpv4_options:
554-
dhcpv4_options = []
555-
elif 'cmd' in port_info.dhcpv4_options:
556-
dhcpv4_options = txn.add(port_info.dhcpv4_options['cmd'])
557-
else:
558-
dhcpv4_options = [port_info.dhcpv4_options['uuid']]
559-
if not port_info.dhcpv6_options:
560-
dhcpv6_options = []
561-
elif 'cmd' in port_info.dhcpv6_options:
562-
dhcpv6_options = txn.add(port_info.dhcpv6_options['cmd'])
563-
else:
564-
dhcpv6_options = [port_info.dhcpv6_options['uuid']]
575+
dhcpv4_options, dhcpv6_options = self.update_port_dhcp_options(
576+
port_info, txn=txn)
565577
# The lport_name *must* be neutron port['id']. It must match the
566578
# iface-id set in the Interfaces table of the Open_vSwitch
567579
# database which nova sets to be the port ID.
@@ -675,18 +687,9 @@ def update_port(self, context, port, port_object=None):
675687
else:
676688
columns_dict['type'] = port_info.type
677689
columns_dict['addresses'] = port_info.addresses
678-
if not port_info.dhcpv4_options:
679-
dhcpv4_options = []
680-
elif 'cmd' in port_info.dhcpv4_options:
681-
dhcpv4_options = txn.add(port_info.dhcpv4_options['cmd'])
682-
else:
683-
dhcpv4_options = [port_info.dhcpv4_options['uuid']]
684-
if not port_info.dhcpv6_options:
685-
dhcpv6_options = []
686-
elif 'cmd' in port_info.dhcpv6_options:
687-
dhcpv6_options = txn.add(port_info.dhcpv6_options['cmd'])
688-
else:
689-
dhcpv6_options = [port_info.dhcpv6_options['uuid']]
690+
691+
dhcpv4_options, dhcpv6_options = self.update_port_dhcp_options(
692+
port_info, txn=txn)
690693

691694
if self.is_metadata_port(port):
692695
context = n_context.get_admin_context()

0 commit comments

Comments
 (0)