ovn-migration: Introduce migrate mode to DB sync tool
The new "migrate" mode for the DB sync utility changes DB contents as follows: - it changes vxlan networks to Geneve, including its allocation in order to avoid future collisions when creating new geneve networks - it removes settings from ports' vif_details that are no longer needed, such as hybrid plugging or bridge_name for the trunk bridges - it sets profile for subports - OVN doesn't use trunk_details but port profile to store data about trunk. Subports have tag and parent_name fileds. Previously, the vxlan to Geneve change was done via ansible role. The tasks in the role were replaced by the script therefore the role is removed. Signed-off-by: Jakub Libosvar <libosvar@redhat.com> Change-Id: I29a39108d9fddb30050ec63a1cdf6bba0400e136
This commit is contained in:
parent
07c0cc4a66
commit
ae78e812d1
@ -24,6 +24,7 @@ from neutron.conf.agent import securitygroups_rpc
|
|||||||
from neutron.conf.plugins.ml2.drivers.ovn import ovn_conf
|
from neutron.conf.plugins.ml2.drivers.ovn import ovn_conf
|
||||||
from neutron import manager
|
from neutron import manager
|
||||||
from neutron import opts as neutron_options
|
from neutron import opts as neutron_options
|
||||||
|
from neutron.plugins.ml2.drivers.ovn import db_migration
|
||||||
from neutron.plugins.ml2.drivers.ovn.mech_driver import mech_driver
|
from neutron.plugins.ml2.drivers.ovn.mech_driver import mech_driver
|
||||||
from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb import impl_idl_ovn
|
from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb import impl_idl_ovn
|
||||||
from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb import ovn_db_sync
|
from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb import ovn_db_sync
|
||||||
@ -171,6 +172,11 @@ def main():
|
|||||||
logging.setup(conf, 'neutron_ovn_db_sync_util')
|
logging.setup(conf, 'neutron_ovn_db_sync_util')
|
||||||
LOG.info('Started Neutron OVN db sync')
|
LOG.info('Started Neutron OVN db sync')
|
||||||
mode = ovn_conf.get_ovn_neutron_sync_mode()
|
mode = ovn_conf.get_ovn_neutron_sync_mode()
|
||||||
|
# Migrate mode will run as repair mode in the synchronizer
|
||||||
|
migrate = False
|
||||||
|
if mode == ovn_conf.MIGRATE_MODE:
|
||||||
|
mode = ovn_db_sync.SYNC_MODE_REPAIR
|
||||||
|
migrate = True
|
||||||
if mode not in [ovn_db_sync.SYNC_MODE_LOG, ovn_db_sync.SYNC_MODE_REPAIR]:
|
if mode not in [ovn_db_sync.SYNC_MODE_LOG, ovn_db_sync.SYNC_MODE_REPAIR]:
|
||||||
LOG.error(
|
LOG.error(
|
||||||
'Invalid sync mode : ["%s"]. Should be "log" or "repair"', mode)
|
'Invalid sync mode : ["%s"]. Should be "log" or "repair"', mode)
|
||||||
@ -235,3 +241,8 @@ def main():
|
|||||||
LOG.info('Sync for Southbound db started with mode : %s', mode)
|
LOG.info('Sync for Southbound db started with mode : %s', mode)
|
||||||
sb_synchronizer.do_sync()
|
sb_synchronizer.do_sync()
|
||||||
LOG.info('Sync completed for Southbound db')
|
LOG.info('Sync completed for Southbound db')
|
||||||
|
|
||||||
|
if migrate:
|
||||||
|
LOG.info("Migrating Neutron database from OVS to OVN")
|
||||||
|
db_migration.migrate_neutron_database_to_ovn(core_plugin)
|
||||||
|
LOG.info("Neutron database migration from OVS to OVN completed")
|
||||||
|
@ -26,6 +26,8 @@ EXTRA_LOG_LEVEL_DEFAULTS = [
|
|||||||
VLOG_LEVELS = {'CRITICAL': vlog.CRITICAL, 'ERROR': vlog.ERROR, 'WARNING':
|
VLOG_LEVELS = {'CRITICAL': vlog.CRITICAL, 'ERROR': vlog.ERROR, 'WARNING':
|
||||||
vlog.WARN, 'INFO': vlog.INFO, 'DEBUG': vlog.DEBUG}
|
vlog.WARN, 'INFO': vlog.INFO, 'DEBUG': vlog.DEBUG}
|
||||||
|
|
||||||
|
MIGRATE_MODE = "migrate"
|
||||||
|
|
||||||
ovn_opts = [
|
ovn_opts = [
|
||||||
cfg.StrOpt('ovn_nb_connection',
|
cfg.StrOpt('ovn_nb_connection',
|
||||||
default='tcp:127.0.0.1:6641',
|
default='tcp:127.0.0.1:6641',
|
||||||
@ -85,7 +87,7 @@ ovn_opts = [
|
|||||||
'to 60 seconds.')),
|
'to 60 seconds.')),
|
||||||
cfg.StrOpt('neutron_sync_mode',
|
cfg.StrOpt('neutron_sync_mode',
|
||||||
default='log',
|
default='log',
|
||||||
choices=('off', 'log', 'repair'),
|
choices=('off', 'log', 'repair', MIGRATE_MODE),
|
||||||
help=_('The synchronization mode of OVN_Northbound OVSDB '
|
help=_('The synchronization mode of OVN_Northbound OVSDB '
|
||||||
'with Neutron DB.\n'
|
'with Neutron DB.\n'
|
||||||
'off - synchronization is off \n'
|
'off - synchronization is off \n'
|
||||||
@ -97,7 +99,11 @@ ovn_opts = [
|
|||||||
'repair - during neutron-server startup, automatically'
|
'repair - during neutron-server startup, automatically'
|
||||||
' create resources found in Neutron but not in OVN.'
|
' create resources found in Neutron but not in OVN.'
|
||||||
' Also remove resources from OVN'
|
' Also remove resources from OVN'
|
||||||
' that are no longer in Neutron.')),
|
' that are no longer in Neutron.'
|
||||||
|
'%(migrate)s - This mode is to OVS to OVN migration. It'
|
||||||
|
' will sync the DB just like repair mode but it will'
|
||||||
|
' additionally fix the Neutron DB resource from OVS to'
|
||||||
|
' OVN.') % {'migrate': MIGRATE_MODE}),
|
||||||
cfg.BoolOpt('ovn_l3_mode',
|
cfg.BoolOpt('ovn_l3_mode',
|
||||||
default=True,
|
default=True,
|
||||||
deprecated_for_removal=True,
|
deprecated_for_removal=True,
|
||||||
|
83
neutron/plugins/ml2/drivers/ovn/db_migration.py
Normal file
83
neutron/plugins/ml2/drivers/ovn/db_migration.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
# Copyright 2021 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from neutron_lib.api.definitions import portbindings as pb_api
|
||||||
|
from neutron_lib import context as n_context
|
||||||
|
from neutron_lib.db import api as db_api
|
||||||
|
|
||||||
|
from neutron.db.models.plugins.ml2 import geneveallocation
|
||||||
|
from neutron.db.models.plugins.ml2 import vxlanallocation
|
||||||
|
from neutron.objects import network as network_obj
|
||||||
|
from neutron.objects import ports as port_obj
|
||||||
|
from neutron.objects import trunk as trunk_obj
|
||||||
|
|
||||||
|
VIF_DETAILS_TO_REMOVE = (
|
||||||
|
pb_api.OVS_HYBRID_PLUG,
|
||||||
|
pb_api.VIF_DETAILS_BRIDGE_NAME,
|
||||||
|
pb_api.VIF_DETAILS_CONNECTIVITY)
|
||||||
|
|
||||||
|
|
||||||
|
def migrate_neutron_database_to_ovn(plugin):
|
||||||
|
"""Change DB content from OVS to OVN mech driver.
|
||||||
|
|
||||||
|
- Changes vxlan network type to Geneve and updates Geneve allocations.
|
||||||
|
- Removes unnecessary settings from port binding vif details, such as
|
||||||
|
connectivity, bridge_name and ovs_hybrid_plug, as they are not used by
|
||||||
|
OVN.
|
||||||
|
"""
|
||||||
|
ctx = n_context.get_admin_context()
|
||||||
|
with db_api.CONTEXT_WRITER.using(ctx) as session:
|
||||||
|
# Change network type from vxlan geneve
|
||||||
|
segments = network_obj.NetworkSegment.get_objects(
|
||||||
|
ctx, network_type='vxlan')
|
||||||
|
for segment in segments:
|
||||||
|
segment.network_type = 'geneve'
|
||||||
|
segment.update()
|
||||||
|
# Update Geneve allocation for the segment
|
||||||
|
session.query(geneveallocation.GeneveAllocation).filter(
|
||||||
|
geneveallocation.GeneveAllocation.geneve_vni ==
|
||||||
|
segment.segmentation_id).update({"allocated": True})
|
||||||
|
# Zero Vxlan allocations
|
||||||
|
session.query(vxlanallocation.VxlanAllocation).filter(
|
||||||
|
vxlanallocation.VxlanAllocation.vxlan_vni ==
|
||||||
|
segment.segmentation_id).update({"allocated": False})
|
||||||
|
|
||||||
|
port_bindings = port_obj.PortBinding.get_objects(
|
||||||
|
ctx, vif_type='ovs', vnic_type='normal', status='ACTIVE')
|
||||||
|
for pb in port_bindings:
|
||||||
|
if not pb.vif_details:
|
||||||
|
continue
|
||||||
|
vif_details = pb.vif_details.copy()
|
||||||
|
for detail in VIF_DETAILS_TO_REMOVE:
|
||||||
|
try:
|
||||||
|
del vif_details[detail]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
if vif_details != pb.vif_details:
|
||||||
|
pb.vif_details = vif_details
|
||||||
|
pb.update()
|
||||||
|
|
||||||
|
for trunk in trunk_obj.Trunk.get_objects(ctx):
|
||||||
|
for subport in trunk.sub_ports:
|
||||||
|
pbs = port_obj.PortBinding.get_objects(
|
||||||
|
ctx, port_id=subport.port_id)
|
||||||
|
for pb in pbs:
|
||||||
|
profile = {}
|
||||||
|
if pb.profile:
|
||||||
|
profile = pb.profile.copy()
|
||||||
|
profile['parent_name'] = trunk.port_id
|
||||||
|
profile['tag'] = subport.segmentation_id
|
||||||
|
if profile != pb.profile:
|
||||||
|
pb.profile = profile
|
||||||
|
pb.update()
|
@ -66,7 +66,7 @@ from neutron.tests.unit.plugins.ml2 import test_security_group
|
|||||||
OVN_PROFILE = ovn_const.OVN_PORT_BINDING_PROFILE
|
OVN_PROFILE = ovn_const.OVN_PORT_BINDING_PROFILE
|
||||||
|
|
||||||
|
|
||||||
class TestOVNMechanismDriver(test_plugin.Ml2PluginV2TestCase):
|
class TestOVNMechanismDriverBase(test_plugin.Ml2PluginV2TestCase):
|
||||||
|
|
||||||
_mechanism_drivers = ['logger', 'ovn']
|
_mechanism_drivers = ['logger', 'ovn']
|
||||||
_extension_drivers = ['port_security', 'dns']
|
_extension_drivers = ['port_security', 'dns']
|
||||||
@ -87,7 +87,7 @@ class TestOVNMechanismDriver(test_plugin.Ml2PluginV2TestCase):
|
|||||||
group='ovn')
|
group='ovn')
|
||||||
cfg.CONF.set_override('vlan_transparent', True)
|
cfg.CONF.set_override('vlan_transparent', True)
|
||||||
mock.patch.object(impl_idl_ovn.Backend, 'schema_helper').start()
|
mock.patch.object(impl_idl_ovn.Backend, 'schema_helper').start()
|
||||||
super(TestOVNMechanismDriver, self).setUp()
|
super().setUp()
|
||||||
mm = directory.get_plugin().mechanism_manager
|
mm = directory.get_plugin().mechanism_manager
|
||||||
self.mech_driver = mm.mech_drivers['ovn'].obj
|
self.mech_driver = mm.mech_drivers['ovn'].obj
|
||||||
neutron_agent.AgentCache(self.mech_driver)
|
neutron_agent.AgentCache(self.mech_driver)
|
||||||
@ -121,6 +121,8 @@ class TestOVNMechanismDriver(test_plugin.Ml2PluginV2TestCase):
|
|||||||
p.start()
|
p.start()
|
||||||
self.addCleanup(p.stop)
|
self.addCleanup(p.stop)
|
||||||
|
|
||||||
|
|
||||||
|
class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
||||||
@mock.patch.object(ovsdb_monitor.OvnInitPGNbIdl, 'from_server')
|
@mock.patch.object(ovsdb_monitor.OvnInitPGNbIdl, 'from_server')
|
||||||
@mock.patch.object(ovsdb_monitor, 'short_living_ovsdb_api')
|
@mock.patch.object(ovsdb_monitor, 'short_living_ovsdb_api')
|
||||||
def test__create_neutron_pg_drop_non_existing(
|
def test__create_neutron_pg_drop_non_existing(
|
||||||
|
158
neutron/tests/unit/plugins/ml2/drivers/ovn/test_db_migration.py
Normal file
158
neutron/tests/unit/plugins/ml2/drivers/ovn/test_db_migration.py
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
# Copyright 2021 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from neutron_lib.api.definitions import portbindings as pb
|
||||||
|
from neutron_lib.api.definitions import provider_net as pnet
|
||||||
|
from neutron_lib import context as n_context
|
||||||
|
from neutron_lib.db import api as db_api
|
||||||
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
|
from neutron.db.models.plugins.ml2 import geneveallocation
|
||||||
|
from neutron.db.models.plugins.ml2 import vxlanallocation
|
||||||
|
from neutron.objects import ports as port_obj
|
||||||
|
from neutron.objects import trunk as trunk_obj
|
||||||
|
from neutron.plugins.ml2.drivers.ovn import db_migration
|
||||||
|
from neutron.tests.unit.plugins.ml2.drivers.ovn.mech_driver import (
|
||||||
|
test_mech_driver)
|
||||||
|
|
||||||
|
|
||||||
|
class TestMigrateNeutronDatabaseToOvn(
|
||||||
|
test_mech_driver.TestOVNMechanismDriverBase):
|
||||||
|
|
||||||
|
def _create_ml2_ovs_test_resources(self, vif_details_list):
|
||||||
|
self.subport_profiles = {}
|
||||||
|
ctx = n_context.get_admin_context()
|
||||||
|
for sid in range(1, 6):
|
||||||
|
net_arg = {pnet.NETWORK_TYPE: 'vxlan',
|
||||||
|
pnet.SEGMENTATION_ID: sid}
|
||||||
|
network_id = self._make_network(self.fmt, 'net%d' % sid, True,
|
||||||
|
arg_list=(pnet.NETWORK_TYPE,
|
||||||
|
pnet.SEGMENTATION_ID,),
|
||||||
|
**net_arg)['network']['id']
|
||||||
|
|
||||||
|
for vif_details in vif_details_list:
|
||||||
|
port = self._make_port(self.fmt, network_id)['port']
|
||||||
|
port_o = port_obj.PortBinding.get_object(
|
||||||
|
ctx, port_id=port['id'], host='')
|
||||||
|
port_o.vif_type = 'ovs'
|
||||||
|
port_o.vif_details = vif_details
|
||||||
|
port_o.update()
|
||||||
|
|
||||||
|
for i in range(1, 4):
|
||||||
|
port = self._make_port(self.fmt, network_id)['port']
|
||||||
|
subport1 = self._make_port(self.fmt, network_id)['port']
|
||||||
|
subport2 = self._make_port(self.fmt, network_id)['port']
|
||||||
|
|
||||||
|
trunk_id = uuidutils.generate_uuid()
|
||||||
|
|
||||||
|
subports = [trunk_obj.SubPort(
|
||||||
|
ctx,
|
||||||
|
port_id=subport1['id'],
|
||||||
|
trunk_id=trunk_id,
|
||||||
|
segmentation_type="vlan",
|
||||||
|
segmentation_id=i * 10 + j) for j in range(2)]
|
||||||
|
|
||||||
|
trunk = trunk_obj.Trunk(
|
||||||
|
ctx,
|
||||||
|
id=trunk_id,
|
||||||
|
port_id=port['id'],
|
||||||
|
project_id='foo',
|
||||||
|
subports=subports)
|
||||||
|
trunk.create()
|
||||||
|
|
||||||
|
subport_pb = port_obj.PortBinding.get_object(
|
||||||
|
ctx, port_id=subport1['id'], host='')
|
||||||
|
self.assertFalse(subport_pb.profile)
|
||||||
|
|
||||||
|
self.subport_profiles[subport1['id']] = {"parent_name": port['id'],
|
||||||
|
"tag": i * 10}
|
||||||
|
self.subport_profiles[subport2['id']] = {"parent_name": port['id'],
|
||||||
|
"tag": i * 10 + 1}
|
||||||
|
|
||||||
|
# set something to the last subport port binding
|
||||||
|
subport_pb = port_obj.PortBinding.get_object(
|
||||||
|
ctx, port_id=subport2['id'], host='')
|
||||||
|
# need to generate new id
|
||||||
|
subport_pb.profile = subport_pb.profile.copy()
|
||||||
|
subport_pb.profile['foo'] = 'bar'
|
||||||
|
subport_pb.update()
|
||||||
|
|
||||||
|
self.subport_profiles[subport2['id']]["foo"] = "bar"
|
||||||
|
|
||||||
|
def _validate_resources_after_migration(self, expected_vif_details):
|
||||||
|
ctx = n_context.get_admin_context()
|
||||||
|
|
||||||
|
# Check network types
|
||||||
|
networks = self.plugin.get_networks(ctx)
|
||||||
|
for network in networks:
|
||||||
|
self.assertEqual("geneve", network["provider:network_type"])
|
||||||
|
|
||||||
|
with db_api.CONTEXT_READER.using(ctx) as session:
|
||||||
|
# Check there are no vxlan allocations
|
||||||
|
vxlan_allocations = session.query(
|
||||||
|
vxlanallocation.VxlanAllocation).filter(
|
||||||
|
vxlanallocation.VxlanAllocation.allocated == True # noqa
|
||||||
|
).all()
|
||||||
|
self.assertFalse(vxlan_allocations)
|
||||||
|
|
||||||
|
# Check all the networks have Geneve allocations
|
||||||
|
geneve_allocations = session.query(
|
||||||
|
geneveallocation.GeneveAllocation).filter(
|
||||||
|
geneveallocation.GeneveAllocation.allocated == True # noqa
|
||||||
|
).all()
|
||||||
|
self.assertEqual(len(networks), len(geneve_allocations))
|
||||||
|
|
||||||
|
# Check port bindings vif details are as expected
|
||||||
|
ports = self.plugin.get_ports(ctx)
|
||||||
|
for port in ports:
|
||||||
|
self.assertIn(port['binding:vif_details'], expected_vif_details)
|
||||||
|
|
||||||
|
# Check port profiles for subport ports
|
||||||
|
for trunk in trunk_obj.Trunk.get_objects(ctx):
|
||||||
|
for subport in trunk.sub_ports:
|
||||||
|
port = self.plugin.get_port(ctx, id=subport.port_id)
|
||||||
|
self.assertEqual(
|
||||||
|
self.subport_profiles[subport.port_id],
|
||||||
|
port["binding:profile"])
|
||||||
|
|
||||||
|
def test_db_migration(self):
|
||||||
|
"""Test the DB migration
|
||||||
|
|
||||||
|
It creates 5 vxlan networks, each should get a vxlan vni allocated.
|
||||||
|
Then it creates 3 ports with different vif details.
|
||||||
|
|
||||||
|
After the DB migration the vxlan networks should not be allocated but
|
||||||
|
be geneve type and have geneve allocations. Also the port binding vif
|
||||||
|
details should not contain hybrid plugging, bridge name for trunk and
|
||||||
|
l2 connectivity for OVS agent.
|
||||||
|
"""
|
||||||
|
vif_details_list = [
|
||||||
|
{pb.CAP_PORT_FILTER: "true",
|
||||||
|
pb.OVS_HYBRID_PLUG: "true",
|
||||||
|
pb.VIF_DETAILS_BRIDGE_NAME: "foo",
|
||||||
|
pb.VIF_DETAILS_CONNECTIVITY: "l2"},
|
||||||
|
{pb.CAP_PORT_FILTER: "true",
|
||||||
|
pb.VIF_DETAILS_BRIDGE_NAME: "foo"},
|
||||||
|
{"foo": "bar"},
|
||||||
|
{},
|
||||||
|
]
|
||||||
|
expected_vif_details = [
|
||||||
|
{pb.CAP_PORT_FILTER: "true"},
|
||||||
|
{"foo": "bar"},
|
||||||
|
{},
|
||||||
|
]
|
||||||
|
|
||||||
|
self._create_ml2_ovs_test_resources(vif_details_list)
|
||||||
|
db_migration.migrate_neutron_database_to_ovn(self.mech_driver._plugin)
|
||||||
|
self._validate_resources_after_migration(expected_vif_details)
|
@ -34,15 +34,6 @@
|
|||||||
- migration
|
- migration
|
||||||
|
|
||||||
|
|
||||||
# It runs tasks on ovn-dbs nodes
|
|
||||||
# 1. Change vxlan network type to Geneve
|
|
||||||
- name: Prepare controllers
|
|
||||||
hosts: ovn-dbs
|
|
||||||
roles:
|
|
||||||
- prepare-controllers
|
|
||||||
tags:
|
|
||||||
- migration
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# TripleO / Director is executed to deploy ovn using "br-migration" for the
|
# TripleO / Director is executed to deploy ovn using "br-migration" for the
|
||||||
# dataplane, while br-int is left intact to avoid dataplane disruption.
|
# dataplane, while br-int is left intact to avoid dataplane disruption.
|
||||||
|
@ -8,13 +8,13 @@
|
|||||||
command: podman exec "{{ neutron_id.stdout }}"
|
command: podman exec "{{ neutron_id.stdout }}"
|
||||||
neutron-ovn-db-sync-util --config-file /etc/neutron/neutron.conf
|
neutron-ovn-db-sync-util --config-file /etc/neutron/neutron.conf
|
||||||
--config-file /etc/neutron/plugins/ml2/ml2_conf.ini
|
--config-file /etc/neutron/plugins/ml2/ml2_conf.ini
|
||||||
--ovn-neutron_sync_mode repair
|
--ovn-neutron_sync_mode migrate
|
||||||
|
|
||||||
- name: Sync neutron db with OVN db (container) - Run 2
|
- name: Sync neutron db with OVN db (container) - Run 2
|
||||||
command: podman exec "{{ neutron_id.stdout }}"
|
command: podman exec "{{ neutron_id.stdout }}"
|
||||||
neutron-ovn-db-sync-util --config-file /etc/neutron/neutron.conf
|
neutron-ovn-db-sync-util --config-file /etc/neutron/neutron.conf
|
||||||
--config-file /etc/neutron/plugins/ml2/ml2_conf.ini
|
--config-file /etc/neutron/plugins/ml2/ml2_conf.ini
|
||||||
--ovn-neutron_sync_mode repair
|
--ovn-neutron_sync_mode migrate
|
||||||
|
|
||||||
- name: Pause and let ovn-controllers settle before doing the final activation (5 minute)
|
- name: Pause and let ovn-controllers settle before doing the final activation (5 minute)
|
||||||
pause: minutes=5
|
pause: minutes=5
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
neutron_conf_path: /var/lib/config-data/puppet-generated/neutron/etc/neutron/neutron.conf
|
|
||||||
neutron_conf_tempfile: /tmp/neutron.conf
|
|
@ -1,27 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Fetch neutron configuration
|
|
||||||
fetch:
|
|
||||||
src: "{{ neutron_conf_path }}"
|
|
||||||
dest: "{{ neutron_conf_tempfile }}"
|
|
||||||
flat: yes
|
|
||||||
when: ovn_central is defined
|
|
||||||
|
|
||||||
- name: Get DB connection string
|
|
||||||
set_fact:
|
|
||||||
db_connection_string: "{{ lookup('ini', 'connection section=database file={{ neutron_conf_tempfile }}') }}"
|
|
||||||
when: ovn_central is defined
|
|
||||||
|
|
||||||
# The shell below is not readable well. The code spawns a sqlalchemy engine
|
|
||||||
# and connects to the Neutron database to run following SQL command:
|
|
||||||
# UPDATE networksegments SET networksegments.network_type='geneve' WHERE networksegments.network_type='vxlan';
|
|
||||||
# The indented Python code looks as follows:
|
|
||||||
#
|
|
||||||
# from sqlalchemy import create_engine
|
|
||||||
#
|
|
||||||
# engine = create_engine("{{ mysql_url.stdout }}")
|
|
||||||
# with engine.connect() as conn:
|
|
||||||
# conn.execute("SQL COMMAND")
|
|
||||||
#
|
|
||||||
- name: Change vxlan networks to Geneve
|
|
||||||
shell: podman exec -it neutron_api python3 -c $'from sqlalchemy import create_engine\nengine = create_engine("{{ db_connection_string }}")\nwith engine.connect() as conn:\n\tconn.execute("update networksegments set networksegments.network_type=\'geneve\' where networksegments.network_type=\'vxlan\';")'
|
|
||||||
when: ovn_central is defined
|
|
Loading…
Reference in New Issue
Block a user