Skip to content

Commit efd63d1

Browse files
chrisbugpriteau
authored andcommitted
Error log for missing certs with NB and SB DBs
When the ovn-provider starts up, it attempts to connect to the NB and SB databases by retrieving SSL and cert files. To avoid errors, the code will now check if these files exist before using them. If the files are missing, connections will be skipped and an error message will be displayed in the logs. Refactoring _check_and_set_ssl_files method to be public and reusable. it will now check to see if a string value is set and will now check path and LOG an error message if not found. Adding unit tests for ovsdb_monitor to bring up test coverage. Updated ovsdb_tests to improve code. Closes-Bug: #2072978 Change-Id: I2a21b94fee03767a5f703486bdab2908cda18746
1 parent b5d8693 commit efd63d1

File tree

4 files changed

+124
-38
lines changed

4 files changed

+124
-38
lines changed

ovn_octavia_provider/helper.py

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from oslo_log import log as logging
3030
from oslo_serialization import jsonutils
3131
from oslo_utils import strutils
32-
from ovs.stream import Stream
32+
from ovn_octavia_provider.ovsdb import ovsdb_monitor
3333
from ovsdbapp.backend.ovs_idl import connection
3434
from ovsdbapp.backend.ovs_idl import idlutils
3535
from ovsdbapp.schema.ovn_northbound import commands as cmd
@@ -57,7 +57,7 @@ def __init__(self, notifier=True):
5757
self.helper_thread = threading.Thread(target=self.request_handler)
5858
self.helper_thread.daemon = True
5959
self._octavia_driver_lib = o_driver_lib.DriverLibrary()
60-
self._check_and_set_ssl_files()
60+
ovsdb_monitor.check_and_set_ssl_files('OVN_Northbound')
6161
self._init_lb_actions()
6262

6363
i = impl_idl_ovn.OvnNbIdlForLb(notifier=notifier)
@@ -106,21 +106,6 @@ def _delete_disabled_from_status(status):
106106
for i in v]
107107
for k, v in status.items()}
108108

109-
def _check_and_set_ssl_files(self):
110-
# TODO(reedip): Make ovsdb_monitor's _check_and_set_ssl_files() public
111-
# This is a copy of ovsdb_monitor._check_and_set_ssl_files
112-
priv_key_file = ovn_conf.get_ovn_nb_private_key()
113-
cert_file = ovn_conf.get_ovn_nb_certificate()
114-
ca_cert_file = ovn_conf.get_ovn_nb_ca_cert()
115-
if priv_key_file:
116-
Stream.ssl_set_private_key_file(priv_key_file)
117-
118-
if cert_file:
119-
Stream.ssl_set_certificate_file(cert_file)
120-
121-
if ca_cert_file:
122-
Stream.ssl_set_ca_cert_file(ca_cert_file)
123-
124109
def shutdown(self):
125110
self.requests.put({'type': ovn_const.REQ_TYPE_EXIT},
126111
timeout=ovn_const.MAX_TIMEOUT_REQUEST)

ovn_octavia_provider/ovsdb/impl_idl_ovn.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ class OvnNbIdlForLb(ovsdb_monitor.OvnIdl):
213213

214214
def __init__(self, event_lock_name=None, notifier=True):
215215
self.conn_string = config.get_ovn_nb_connection()
216-
ovsdb_monitor._check_and_set_ssl_files(self.SCHEMA)
216+
ovsdb_monitor.check_and_set_ssl_files(self.SCHEMA)
217217
helper = self._get_ovsdb_helper(self.conn_string)
218218
for table in OvnNbIdlForLb.TABLES:
219219
helper.register_table(table)
@@ -235,7 +235,7 @@ class OvnSbIdlForLb(ovsdb_monitor.OvnIdl):
235235

236236
def __init__(self, event_lock_name=None):
237237
self.conn_string = config.get_ovn_sb_connection()
238-
ovsdb_monitor._check_and_set_ssl_files(self.SCHEMA)
238+
ovsdb_monitor.check_and_set_ssl_files(self.SCHEMA)
239239
helper = self._get_ovsdb_helper(self.conn_string)
240240
for table in OvnSbIdlForLb.TABLES:
241241
helper.register_table(table)

ovn_octavia_provider/ovsdb/ovsdb_monitor.py

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# under the License.
1414

1515
import abc
16+
import os
1617

1718
from oslo_config import cfg
1819
from oslo_log import log
@@ -30,7 +31,7 @@
3031
class BaseOvnIdl(connection.OvsdbIdl):
3132
@classmethod
3233
def from_server(cls, connection_string, schema_name):
33-
_check_and_set_ssl_files(schema_name)
34+
check_and_set_ssl_files(schema_name)
3435
helper = idlutils.get_schema_helper(connection_string, schema_name)
3536
helper.register_all()
3637
return cls(connection_string, helper)
@@ -85,21 +86,33 @@ def __init__(self, driver):
8586
self.driver = driver
8687

8788

88-
def _check_and_set_ssl_files(schema_name):
89-
if schema_name == 'OVN_Northbound':
90-
priv_key_file = ovn_config.get_ovn_nb_private_key()
91-
cert_file = ovn_config.get_ovn_nb_certificate()
92-
ca_cert_file = ovn_config.get_ovn_nb_ca_cert()
93-
94-
Stream.ssl_set_private_key_file(priv_key_file)
95-
Stream.ssl_set_certificate_file(cert_file)
96-
Stream.ssl_set_ca_cert_file(ca_cert_file)
97-
98-
if schema_name == 'OVN_Southbound':
99-
priv_key_file = ovn_config.get_ovn_sb_private_key()
100-
cert_file = ovn_config.get_ovn_sb_certificate()
101-
ca_cert_file = ovn_config.get_ovn_sb_ca_cert()
102-
103-
Stream.ssl_set_private_key_file(priv_key_file)
104-
Stream.ssl_set_certificate_file(cert_file)
105-
Stream.ssl_set_ca_cert_file(ca_cert_file)
89+
def check_and_set_ssl_files(schema_name):
90+
if schema_name in ['OVN_Northbound', 'OVN_Southbound']:
91+
if schema_name == 'OVN_Northbound':
92+
priv_key_file = ovn_config.get_ovn_nb_private_key()
93+
cert_file = ovn_config.get_ovn_nb_certificate()
94+
ca_cert_file = ovn_config.get_ovn_nb_ca_cert()
95+
else:
96+
priv_key_file = ovn_config.get_ovn_sb_private_key()
97+
cert_file = ovn_config.get_ovn_sb_certificate()
98+
ca_cert_file = ovn_config.get_ovn_sb_ca_cert()
99+
100+
if priv_key_file:
101+
if not os.path.exists(priv_key_file):
102+
LOG.error(f"Cannot find private key file for {schema_name}")
103+
else:
104+
Stream.ssl_set_private_key_file(priv_key_file)
105+
106+
if cert_file:
107+
if not os.path.exists(cert_file):
108+
LOG.error(f"Cannot find private cert file for {schema_name}")
109+
else:
110+
Stream.ssl_set_certificate_file(cert_file)
111+
112+
if ca_cert_file:
113+
if not os.path.exists(ca_cert_file):
114+
LOG.error(f"Cannot find ca cert file for {schema_name}")
115+
else:
116+
Stream.ssl_set_ca_cert_file(ca_cert_file)
117+
else:
118+
LOG.error(f"{schema_name} not supported")
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#
2+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
3+
# not use this file except in compliance with the License. You may obtain
4+
# a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11+
# License for the specific language governing permissions and limitations
12+
# under the License.
13+
#
14+
15+
from unittest import mock
16+
17+
from oslo_config import cfg
18+
import testscenarios
19+
20+
from ovn_octavia_provider.ovsdb import ovsdb_monitor
21+
from ovn_octavia_provider.tests.unit import base as base_test
22+
23+
24+
OPTS = ('ovn_nb_private_key', 'ovn_nb_certificate',
25+
'ovn_nb_ca_cert', 'ovn_sb_private_key',
26+
'ovn_sb_certificate', 'ovn_sb_ca_cert')
27+
28+
29+
class TestOvsdbMonitor(testscenarios.WithScenarios,
30+
base_test.TestOvnOctaviaBase):
31+
32+
scenarios = [
33+
('OVN_Northbound', {'schema': 'OVN_Northbound',
34+
'private_key': 'ovn_nb_private_key',
35+
'certificate': 'ovn_nb_certificate',
36+
'ca_cert': 'ovn_nb_ca_cert'}),
37+
('OVN_Southbound', {'schema': 'OVN_Southbound',
38+
'private_key': 'ovn_sb_private_key',
39+
'certificate': 'ovn_sb_certificate',
40+
'ca_cert': 'ovn_sb_ca_cert'})
41+
]
42+
43+
def setUp(self):
44+
super().setUp()
45+
self._register_opts()
46+
self.mock_os_path = mock.patch('os.path.exists').start()
47+
self.mock_stream = mock.patch.object(ovsdb_monitor, 'Stream').start()
48+
49+
@staticmethod
50+
def _register_opts():
51+
for opt in OPTS:
52+
try:
53+
cfg.CONF.register_opt(cfg.StrOpt(opt), group='ovn')
54+
except cfg.DuplicateOptError:
55+
pass
56+
57+
def test_set_ssl(self):
58+
cfg.CONF.set_override(self.private_key, 'key', group='ovn')
59+
cfg.CONF.set_override(self.certificate, 'cert', group='ovn')
60+
cfg.CONF.set_override(self.ca_cert, 'ca-cert', group='ovn')
61+
self.mock_os_path.return_value = True
62+
ovsdb_monitor.check_and_set_ssl_files(self.schema)
63+
self.mock_stream.ssl_set_private_key_file.assert_called_with('key')
64+
self.mock_stream.ssl_set_certificate_file.assert_called_with('cert')
65+
self.mock_stream.ssl_set_ca_cert_file.assert_called_with('ca-cert')
66+
67+
def test_no_key_and_certs(self):
68+
cfg.CONF.set_override(self.private_key, '', group='ovn')
69+
cfg.CONF.set_override(self.certificate, '', group='ovn')
70+
cfg.CONF.set_override(self.ca_cert, '', group='ovn')
71+
self.mock_os_path.return_value = False
72+
ovsdb_monitor.check_and_set_ssl_files(self.schema)
73+
self.mock_stream.ssl_set_private_key_file.assert_not_called()
74+
self.mock_stream.ssl_set_certificate_file.assert_not_called()
75+
self.mock_stream.ssl_set_ca_cert_file.assert_not_called()
76+
77+
def test_no_nonexisting_files(self):
78+
cfg.CONF.set_override(self.private_key, 'key', group='ovn')
79+
cfg.CONF.set_override(self.certificate, 'cert', group='ovn')
80+
cfg.CONF.set_override(self.ca_cert, 'ca-cert', group='ovn')
81+
self.mock_os_path.return_value = False
82+
83+
with self.assertLogs():
84+
ovsdb_monitor.check_and_set_ssl_files(self.schema)
85+
86+
self.mock_stream.ssl_set_private_key_file.assert_not_called()
87+
self.mock_stream.ssl_set_certificate_file.assert_not_called()
88+
self.mock_stream.ssl_set_ca_cert_file.assert_not_called()

0 commit comments

Comments
 (0)