Fix DB connection configuration for `ovn-northd`

We provide our own systemd service files with this change.  To be
able to pass the correct command line arguments to ``ovn-nortrhd``
we need to create a ``/etc/openvswitch/ovn-northd-db-params.conf``
which has the side effect of profoundly changing the behaviour of
the ``ovn-ctl`` tool that the ``ovn-central`` init script makes use
of.  The systemd service files should be upstreamed.

Also fix the ``ovn-remote`` setting in the local OVSDB, handy for
executing management tools on the units.

Update documentation.

Depends-On: I86b530db330d59c7e31d75b05aeaa99415b59324
Change-Id: I0cc74e2fd45e13d8b3e279ebb3de73117aac3e76
This commit is contained in:
Frode Nordahl 2019-10-22 11:43:10 +02:00
parent 1e60877bc2
commit a1070dd259
No known key found for this signature in database
GPG Key ID: 6A5D59A3BA48373F
11 changed files with 229 additions and 58 deletions

1
README.md Symbolic link
View File

@ -0,0 +1 @@
src/README.md

View File

@ -1,9 +1,36 @@
# Overview
OVN provides open source network virtualization for Open vSwitch (OVS).
This charm provides the Northbound and Southbound OVSDB Databases and the
Open Virtual Network (OVN) central control daemon (`ovn-northd`).
> **Note**: The OVN charms are considered preview charms.
# Usage
OVN makes use of Public Key Infrastructure (PKI) to authenticate and authorize
control plane communication. The charm requires a Certificate Authority to be
present in the model as represented by the `certificates` relation.
There is a [OVN overlay bundle](https://github.com/openstack-charmers/openstack-bundles/blob/master/development/overlays/openstack-base-ovn.yaml)
for use in conjunction with the [OpenStack Base bundle](https://github.com/openstack-charmers/openstack-bundles/blob/master/development/openstack-base-bionic-train/bundle.yaml)
which give an example of how you can automate certificate lifecycle management
with the help from [Vault](https://jaas.ai/vault/).
Please refer to the [Open Virtual Network](https://docs.openstack.org/project-deploy-guide/charm-deployment-guide/latest/app-ovn.html) section of
the [OpenStack Charms Deployment Guide](https://docs.openstack.org/project-deploy-guide/charm-deployment-guide/latest/index.html)
for information about deploying OVN with OpenStack.
## Network Spaces support
This charm supports the use of Juju Network Spaces.
By binding the `ovsdb`, `ovsdb-cms` and `ovsdb-peer` endpoints you can
influence which interface will be used for communication with consumers of
the Southbound DB, Cloud Management Systems (CMS) and cluster internal
communication.
juju deploy ovn-central --bind "''=oam-space ovsdb=data-space"
# Bugs
Please report bugs on [Launchpad](https://bugs.launchpad.net/charm-ovn-central/+filebug).

View File

@ -61,8 +61,26 @@ class OVNCentralCharm(charms_openstack.charm.OpenStackCharm):
packages = ['ovn-central']
services = ['ovn-central']
required_relations = ['certificates']
# NOTE(fnordahl) we replace the package sysv init script with our own
# systemd service files.
#
# The issue that triggered this change is that to be able to pass the
# correct command line arguments to ``ovn-nortrhd`` we need to create
# a ``/etc/openvswitch/ovn-northd-db-params.conf`` which has the side
# effect of profoundly changing the behaviour of the ``ovn-ctl`` tool
# that the ``ovn-central`` init script makes use of.
#
# https://github.com/ovn-org/ovn/blob/dc0e10c068c20c4e59c9c86ecee26baf8ed50e90/utilities/ovn-ctl#L323
#
# TODO: The systemd service files should be upstreamed and removed from
# the charm
restart_map = {
'/etc/default/ovn-central': services,
os.path.join(OVS_ETCDIR, 'ovn-northd-db-params.conf'): ['ovn-northd'],
'/lib/systemd/system/ovn-central.service': [],
'/lib/systemd/system/ovn-northd.service': [],
'/lib/systemd/system/ovn-nb-ovsdb.service': [],
'/lib/systemd/system/ovn-sb-ovsdb.service': [],
}
python_version = 3
source_config_key = 'source'
@ -70,7 +88,7 @@ class OVNCentralCharm(charms_openstack.charm.OpenStackCharm):
def install(self):
"""Extend the default install method.
Mask the ``ovn-central`` service before initial installation.
Mask services before initial installation.
This is done to prevent extraneous standalone DB initialization and
subsequent upgrade to clustered DB when configuration is rendered.
@ -81,9 +99,12 @@ class OVNCentralCharm(charms_openstack.charm.OpenStackCharm):
We also configure source before installing as OpenvSwitch and OVN
packages are distributed as part of the UCA.
"""
ovn_central_service_file = '/etc/systemd/system/ovn-central.service'
if not os.path.islink(ovn_central_service_file):
os.symlink('/dev/null', ovn_central_service_file)
service_masks = [
'/etc/systemd/system/ovn-central.service',
]
for service_file in service_masks:
if not os.path.islink(service_file):
os.symlink('/dev/null', service_file)
self.configure_source()
super().install()
@ -151,13 +172,21 @@ class OVNCentralCharm(charms_openstack.charm.OpenStackCharm):
ovn_key(self.adapters_instance),
ovn_cert(self.adapters_instance),
ovn_ca_cert(self.adapters_instance))
self.run('ovs-vsctl',
'set',
'open',
'.',
'external-ids:ovn-remote=ssl:127.0.0.1:{}'
.format(DB_SB_PORT))
if reactive.is_flag_set('leadership.is_leader'):
if (reactive.is_flag_set('leadership.is_leader') and not
reactive.is_flag_set('leadership.set.ready')):
# This is one-time set up at cluster creation and can only be
# done one the OVSDB cluster leader.
#
# It also has to be done after certificates has been written
# to disk and before we do anything else which is why it is
# co-located with the ``configure_tls`` method.
#
# NOTE: There is one individual OVSDB cluster leader for each
# of the OVSDB databases and throughout a deployment lifetime
# they are not necessarilly the same as the charm leader.
#
# However, at bootstrap time the OVSDB cluster leaders will
# coincide with the charm leader.
self.run('ovn-nbctl',
'set-connection',
'pssl:{}'.format(DB_NB_PORT))
@ -171,5 +200,21 @@ class OVNCentralCharm(charms_openstack.charm.OpenStackCharm):
self.run('ovn-sbctl',
'set-connection',
'pssl:{}'.format(DB_SB_PORT))
self.restart_all()
self.restart_all()
break
def configure_ovn_remote(self, ovsdb_interface):
"""Configure the OVN remote setting in the local OVSDB.
The value is used by command line tools run on this unit.
:param ovsdb_interface: OVSDB interface instance
:type ovsdb_interface: reactive.Endpoint derived class
:raises: subprocess.CalledProcessError
"""
self.run('ovs-vsctl',
'set',
'open',
'.',
'external-ids:ovn-remote={}'
.format(','.join(ovsdb_interface.db_sb_connection_strs)))

View File

@ -146,5 +146,6 @@ def render():
ovsdb_peer.cluster_remote_addrs,
ovsdb_peer.db_sb_cluster_port))
if ovn_charm.enable_services():
ovn_charm.configure_ovn_remote(ovsdb_peer)
reactive.set_flag('config.rendered')
ovn_charm.assess_status()

View File

@ -1,5 +1,5 @@
# This is a POSIX shell fragment -*- sh -*-
# This is a systemd EnvironmentFile as documented in systemd.exec(5)
#
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
@ -11,32 +11,26 @@
# OVN_CTL_OPTS: Extra options to pass to ovs-ctl. This is, for example,
# a suitable place to specify --ovn-northd-wrapper=valgrind.
OVN_CTL_OPTS="
--db-nb-file=/var/lib/openvswitch/ovnnb_db.db
--db-nb-cluster-local-addr={{ ovsdb_peer.cluster_local_addr }}
--db-nb-cluster-local-port={{ ovsdb_peer.db_nb_cluster_port }}
--db-nb-cluster-local-proto=ssl
{%if ovsdb_peer and ovsdb_peer.cluster_remote_addrs %}
--ovn-nb-db-ssl-key={{ options.ovn_key }}
--ovn-nb-db-ssl-cert={{ options.ovn_cert }}
--ovn-nb-db-ssl-ca-cert={{ options.ovn_ca_cert }}
--db-nb-cluster-remote-addr={{ ovsdb_peer.cluster_remote_addrs | first }}
--db-nb-cluster-remote-port={{ ovsdb_peer.db_nb_cluster_port }}
--db-nb-cluster-remote-proto=ssl
{% endif %}
--db-sb-file=/var/lib/openvswitch/ovnsb_db.db
--db-sb-cluster-local-addr={{ ovsdb_peer.cluster_local_addr }}
--db-sb-cluster-local-port={{ ovsdb_peer.db_sb_cluster_port }}
--db-sb-cluster-local-proto=ssl
{%if ovsdb_peer and ovsdb_peer.cluster_remote_addrs %}
--ovn-sb-db-ssl-key={{ options.ovn_key }}
--ovn-sb-db-ssl-cert={{ options.ovn_cert }}
--ovn-sb-db-ssl-ca-cert={{ options.ovn_ca_cert }}
--db-sb-cluster-remote-addr={{ ovsdb_peer.cluster_remote_addrs | first }}
--db-nb-cluster-remote-port={{ ovsdb_peer.db_nb_cluster_port }}
OVN_CTL_OPTS=--db-nb-file=/var/lib/openvswitch/ovnnb_db.db \
--db-nb-cluster-local-addr={{ ovsdb_peer.cluster_local_addr }} \
--db-nb-cluster-local-port={{ ovsdb_peer.db_nb_cluster_port }} \
--db-nb-cluster-local-proto=ssl \
--ovn-nb-db-ssl-key={{ options.ovn_key }} \
--ovn-nb-db-ssl-cert={{ options.ovn_cert }} \
--ovn-nb-db-ssl-ca-cert={{ options.ovn_ca_cert }} \
--db-nb-cluster-remote-addr={{ ovsdb_peer.cluster_remote_addrs | first }} \
--db-nb-cluster-remote-port={{ ovsdb_peer.db_nb_cluster_port }} \
--db-nb-cluster-remote-proto=ssl \
--db-sb-file=/var/lib/openvswitch/ovnsb_db.db \
--db-sb-cluster-local-addr={{ ovsdb_peer.cluster_local_addr }} \
--db-sb-cluster-local-port={{ ovsdb_peer.db_sb_cluster_port }} \
--db-sb-cluster-local-proto=ssl \
--ovn-sb-db-ssl-key={{ options.ovn_key }} \
--ovn-sb-db-ssl-cert={{ options.ovn_cert }} \
--ovn-sb-db-ssl-ca-cert={{ options.ovn_ca_cert }} \
--db-sb-cluster-remote-addr={{ ovsdb_peer.cluster_remote_addrs | first }} \
--db-nb-cluster-remote-port={{ ovsdb_peer.db_nb_cluster_port }} \
--db-sb-cluster-remote-proto=ssl
{% endif %}
"
# DPDK options are now configured via ovs-vsctl/ovsdb, see:
# - /usr/share/doc/openvswitch-common/INSTALL.DPDK.md.gz

View File

@ -0,0 +1,24 @@
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
# Configuration managed by ovn-central charm
###############################################################################
[Unit]
Description=Open Virtual Network central components
After=network.target
After=openvswitch-switch.service
Requires=network.target
Requires=openvswitch-switch.service
Requires=ovn-northd.service
# Facilitate spread placement of the DBs if someone should choose to do that
Wants=ovn-nb-ovsdb.service
Wants=ovn-sb-ovsdb.service
[Service]
Type=oneshot
ExecStart=/bin/true
ExecStop=/bin/true
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,20 @@
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
# Configuration managed by ovn-central charm
###############################################################################
[Unit]
Description=Open vSwitch database server for OVN Northbound database
After=network.target openvswitch-switch.service
PartOf=ovn-central.service
DefaultDependencies=no
[Service]
EnvironmentFile=-/etc/default/ovn-central
Type=forking
PIDFile=/var/run/openvswitch/ovnnb_db.pid
ExecStart=/usr/share/openvswitch/scripts/ovn-ctl start_nb_ovsdb $OVN_CTL_OPTS
ExecStop=/usr/share/openvswitch/scripts/ovn-ctl start_nb_ovsdb
Restart=on-failure
LimitNOFILE=65535
TimeoutStopSec=15

View File

@ -0,0 +1,5 @@
--ovnnb-db={{ ovsdb_peer.db_nb_connection_strs|join(',') }}
--ovnsb-db={{ ovsdb_peer.db_sb_connection_strs|join(',') }}
-c {{ options.ovn_cert }}
-C {{ options.ovn_ca_cert }}
-p {{ options.ovn_key }}

View File

@ -0,0 +1,20 @@
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
# Configuration managed by ovn-central charm
###############################################################################
[Unit]
Description=Open Virtual Network central control daemon
After=network.target ovn-nb-ovsdb.service ovn-sb-ovsdb.service
PartOf=ovn-central.service
DefaultDependencies=no
[Service]
EnvironmentFile=-/etc/default/ovn-central
Type=forking
PIDFile=/var/run/openvswitch/ovn-northd.pid
ExecStart=/usr/share/openvswitch/scripts/ovn-ctl start_northd --ovn-manage-ovsdb=no $OVN_CTL_OPTS
ExecStop=/usr/share/openvswitch/scripts/ovn-ctl stop_northd
Restart=on-failure
LimitNOFILE=65535
TimeoutStopSec=15

View File

@ -0,0 +1,20 @@
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
# Configuration managed by ovn-central charm
###############################################################################
[Unit]
Description=Open vSwitch database server for OVN Southbound database
After=network.target openvswitch-switch.service
PartOf=ovn-central.service
DefaultDependencies=no
[Service]
EnvironmentFile=-/etc/default/ovn-central
Type=forking
PIDFile=/var/run/openvswitch/ovnsb_db.pid
ExecStart=/usr/share/openvswitch/scripts/ovn-ctl start_sb_ovsdb $OVN_CTL_OPTS
ExecStop=/usr/share/openvswitch/scripts/ovn-ctl start_sb_ovsdb
Restart=on-failure
LimitNOFILE=65535
TimeoutStopSec=15

View File

@ -64,11 +64,17 @@ class TestOVNCentralCharm(Helper):
self.patch_object(ovn_central.os, 'symlink')
self.patch_target('configure_source')
self.target.install()
self.islink.assert_called_once_with(
'/etc/systemd/system/ovn-central.service')
self.symlink.assert_called_once_with(
'/dev/null',
'/etc/systemd/system/ovn-central.service')
calls = []
for service in self.target.services:
calls.append(
mock.call('/etc/systemd/system/{}.service'.format(service)))
self.islink.assert_has_calls(calls)
calls = []
for service in self.target.services:
calls.append(
mock.call('/dev/null',
'/etc/systemd/system/{}.service'.format(service)))
self.symlink.assert_has_calls(calls)
self.install.assert_called_once_with()
self.configure_source.assert_called_once_with()
@ -91,7 +97,10 @@ class TestOVNCentralCharm(Helper):
self.assertFalse(self.service_resume.called)
self.target.check_if_paused.return_value = (None, None)
self.target.enable_services()
self.service_resume.assert_called_once_with('ovn-central')
calls = []
for service in self.target.services:
calls.append(mock.call(service))
self.service_resume.assert_has_calls(calls)
def test_run(self):
self.patch_object(ovn_central.subprocess, 'run')
@ -129,7 +138,7 @@ class TestOVNCentralCharm(Helper):
mocked_open.return_value = mocked_file
self.target.configure_cert = mock.MagicMock()
self.target.run = mock.MagicMock()
self.is_flag_set.return_value = True
self.is_flag_set.side_effect = [True, False]
self.target.configure_tls()
mocked_open.assert_called_once_with(
'/etc/openvswitch/ovn-central.crt', 'w')
@ -146,11 +155,6 @@ class TestOVNCentralCharm(Helper):
'/etc/openvswitch/key_host',
'/etc/openvswitch/cert_host',
'/etc/openvswitch/ovn-central.crt'),
mock.call('ovs-vsctl',
'set',
'open',
'.',
'external-ids:ovn-remote=ssl:127.0.0.1:6642'),
mock.call('ovn-nbctl',
'set-connection',
'pssl:6641'),
@ -158,7 +162,7 @@ class TestOVNCentralCharm(Helper):
'set-connection',
'pssl:6642'),
])
self.is_flag_set.return_value = False
self.is_flag_set.side_effect = [False, True]
self.target.run.reset_mock()
self.target.configure_tls()
self.target.run.assert_has_calls([
@ -167,9 +171,19 @@ class TestOVNCentralCharm(Helper):
'/etc/openvswitch/key_host',
'/etc/openvswitch/cert_host',
'/etc/openvswitch/ovn-central.crt'),
mock.call('ovs-vsctl',
'set',
'open',
'.',
'external-ids:ovn-remote=ssl:127.0.0.1:6642'),
])
def test_configure_ovn_remote(self):
self.patch_target('run')
ovsdb_interface = mock.MagicMock()
ovsdb_interface.db_sb_connection_strs = \
mock.PropertyMock().return_value = [
'ssl:a.b.c.d:6642',
'ssl:a.b.c.d:6642',
'ssl:a.b.c.d:6642',
]
self.target.configure_ovn_remote(ovsdb_interface)
self.run.assert_called_once_with(
'ovs-vsctl', 'set', 'open', '.',
'external-ids:ovn-remote='
'ssl:a.b.c.d:6642,ssl:a.b.c.d:6642,ssl:a.b.c.d:6642')