Fix IPv6 router on UC re-install
Running 'openstack undercloud install' a second
time failed with a ConflictException because a subnet
with a router port cannot have the gateway_ip updated.
Ensure that the router port is always deleted prior to
the subnet update and then add the router port again
after updating the subnet
Closes-Bug: #1955417
Change-Id: I0e075153e99876ddf613caecc92b4442e8b6ca03
(cherry picked from commit 62ded067d5
)
This commit is contained in:
parent
40dcc728c6
commit
31a431d351
|
@ -175,16 +175,42 @@ def _neutron_segment_update(sdk, segment_id, name):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def _ensure_neutron_router(sdk, name, subnet_id):
|
def _ensure_neutron_router(sdk, subnet):
|
||||||
# If the router already exist, don't try to create it again.
|
|
||||||
if list(sdk.network.routers(name=name)):
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
router = sdk.network.create_router(name=name, admin_state_up='true')
|
router = sdk.network.find_router(name_or_id=subnet.name)
|
||||||
sdk.network.add_interface_to_router(router.id, subnet_id=subnet_id)
|
if router is None:
|
||||||
|
sdk.network.create_router(name=subnet.name,
|
||||||
|
admin_state_up='true')
|
||||||
except Exception:
|
except Exception:
|
||||||
print('ERROR: Create router for subnet %s failed.' % name)
|
print('ERROR: Create router for subnet %s failed.' % subnet.name)
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def _add_router_port(sdk, subnet):
|
||||||
|
try:
|
||||||
|
router = sdk.network.find_router(name_or_id=subnet.name)
|
||||||
|
sdk.network.add_interface_to_router(router.id, subnet_id=subnet.id)
|
||||||
|
except Exception:
|
||||||
|
print('ERROR: Add router port for subnet %s failed.' % subnet.name)
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_router_port(sdk, subnet):
|
||||||
|
try:
|
||||||
|
router = sdk.network.find_router(name_or_id=subnet.name)
|
||||||
|
if router is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
router_port = next(sdk.network.ports(
|
||||||
|
network_id=subnet.network_id,
|
||||||
|
device_owner='network:router_interface'))
|
||||||
|
sdk.network.remove_interface_from_router(router.id, subnet.id,
|
||||||
|
router_port.id)
|
||||||
|
except StopIteration:
|
||||||
|
# There is no router port
|
||||||
|
pass
|
||||||
|
except Exception:
|
||||||
|
print('ERROR: Delete router %s failed.' % subnet.name)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
@ -224,11 +250,20 @@ def _local_neutron_segments_and_subnets(sdk, ctlplane_id, net_cidrs):
|
||||||
"""Create's and updates the ctlplane subnet on the segment that is local to
|
"""Create's and updates the ctlplane subnet on the segment that is local to
|
||||||
the underclud.
|
the underclud.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
s = CONF['subnets'][CONF['local_subnet']]
|
s = CONF['subnets'][CONF['local_subnet']]
|
||||||
|
# If the subnet is IPv6 we need to start a router so that router
|
||||||
|
# advertisements are sent out for stateless IP addressing to work.
|
||||||
|
# NOTE(hjensas): Don't do this for routed networks. The router will
|
||||||
|
# use the address defined as gateway for the subnet, and in a
|
||||||
|
# deployment with routed networks this will conflict with the router
|
||||||
|
# in the infrastructure. The router in the infrastructure must be
|
||||||
|
# configured to send router advertisements.
|
||||||
|
enable_ipv6_router = (CONF['enable_routed_networks'] is False
|
||||||
|
and netaddr.IPNetwork(s['NetworkCidr']).version == 6)
|
||||||
name = CONF['local_subnet']
|
name = CONF['local_subnet']
|
||||||
subnet = _get_subnet(sdk, s['NetworkCidr'], ctlplane_id)
|
subnet = _get_subnet(sdk, s['NetworkCidr'], ctlplane_id)
|
||||||
segment = _get_segment(sdk, CONF['physical_network'], ctlplane_id)
|
segment = _get_segment(sdk, CONF['physical_network'], ctlplane_id)
|
||||||
|
|
||||||
if subnet:
|
if subnet:
|
||||||
if CONF['enable_routed_networks'] and subnet.segment_id is None:
|
if CONF['enable_routed_networks'] and subnet.segment_id is None:
|
||||||
# The subnet exists and does not have a segment association. Since
|
# The subnet exists and does not have a segment association. Since
|
||||||
|
@ -237,6 +272,12 @@ def _local_neutron_segments_and_subnets(sdk, ctlplane_id, net_cidrs):
|
||||||
# networks subnet by associating the network segment_id with the
|
# networks subnet by associating the network segment_id with the
|
||||||
# subnet.
|
# subnet.
|
||||||
_neutron_add_subnet_segment_association(sdk, subnet.id, segment.id)
|
_neutron_add_subnet_segment_association(sdk, subnet.id, segment.id)
|
||||||
|
|
||||||
|
# The router interface must be removed prior to updating the subnet
|
||||||
|
# in case the gateway_ip of the subnet changed.
|
||||||
|
if enable_ipv6_router:
|
||||||
|
_remove_router_port(sdk, subnet)
|
||||||
|
|
||||||
_neutron_subnet_update(
|
_neutron_subnet_update(
|
||||||
sdk, subnet.id, s['NetworkCidr'], s['NetworkGateway'],
|
sdk, subnet.id, s['NetworkCidr'], s['NetworkGateway'],
|
||||||
s['HostRoutes'], s.get('AllocationPools'), name,
|
s['HostRoutes'], s.get('AllocationPools'), name,
|
||||||
|
@ -246,20 +287,16 @@ def _local_neutron_segments_and_subnets(sdk, ctlplane_id, net_cidrs):
|
||||||
segment_id = segment.id
|
segment_id = segment.id
|
||||||
else:
|
else:
|
||||||
segment_id = None
|
segment_id = None
|
||||||
|
|
||||||
subnet = _neutron_subnet_create(
|
subnet = _neutron_subnet_create(
|
||||||
sdk, ctlplane_id, s['NetworkCidr'], s['NetworkGateway'],
|
sdk, ctlplane_id, s['NetworkCidr'], s['NetworkGateway'],
|
||||||
s['HostRoutes'], s.get('AllocationPools'), name, segment_id,
|
s['HostRoutes'], s.get('AllocationPools'), name, segment_id,
|
||||||
s['DnsNameServers'])
|
s['DnsNameServers'])
|
||||||
# If the subnet is IPv6 we need to start a router so that router
|
|
||||||
# advertisments are sent out for stateless IP addressing to work.
|
if enable_ipv6_router:
|
||||||
# NOTE(hjensas): Don't do this for routed networks. The router will
|
_ensure_neutron_router(sdk, subnet)
|
||||||
# use the address defined as gateway for the subnet, and in a
|
_add_router_port(sdk, subnet)
|
||||||
# deployment with routed networks this will conflict with the router
|
|
||||||
# in the infrastructure. The router in the infrastucture must be
|
|
||||||
# configured to send router advertisements.
|
|
||||||
if not CONF['enable_routed_networks']:
|
|
||||||
if netaddr.IPNetwork(s['NetworkCidr']).version == 6:
|
|
||||||
_ensure_neutron_router(sdk, name, subnet.id)
|
|
||||||
net_cidrs.append(s['NetworkCidr'])
|
net_cidrs.append(s['NetworkCidr'])
|
||||||
|
|
||||||
return net_cidrs
|
return net_cidrs
|
||||||
|
|
Loading…
Reference in New Issue