18
18
from neutron .common .ovn import constants
19
19
from neutron .conf .plugins .ml2 import config as ml2_conf
20
20
from neutron .conf .plugins .ml2 .drivers .ovn import ovn_conf
21
+ from neutron .plugins .ml2 import db as ml2_db
21
22
from neutron .plugins .ml2 .drivers .ovn .mech_driver .ovsdb import ovn_client
22
23
from neutron .tests import base
23
24
from neutron .tests .unit .services .logapi .drivers .ovn \
26
27
from neutron_lib import constants as const
27
28
from neutron_lib .services .logapi import constants as log_const
28
29
30
+ from tenacity import wait_none
31
+
29
32
30
33
class TestOVNClientBase (base .BaseTestCase ):
31
34
@@ -45,6 +48,9 @@ def setUp(self):
45
48
self .get_plugin = mock .patch (
46
49
'neutron_lib.plugins.directory.get_plugin' ).start ()
47
50
51
+ # Disable tenacity wait for UT
52
+ self .ovn_client ._wait_for_port_bindings_host .retry .wait = wait_none ()
53
+
48
54
def test__add_router_ext_gw_default_route (self ):
49
55
plugin = mock .MagicMock ()
50
56
self .get_plugin .return_value = plugin
@@ -114,6 +120,45 @@ def test_update_lsp_host_info_up(self):
114
120
'Logical_Switch_Port' , port_id ,
115
121
('external_ids' , {constants .OVN_HOST_ID_EXT_ID_KEY : host_id }))
116
122
123
+ def test_update_lsp_host_info_up_retry (self ):
124
+ context = mock .MagicMock ()
125
+ host_id = 'fake-binding-host-id'
126
+ port_id = 'fake-port-id'
127
+ db_port_no_host = mock .Mock (
128
+ id = port_id , port_bindings = [mock .Mock (host = "" )])
129
+ db_port = mock .Mock (
130
+ id = port_id , port_bindings = [mock .Mock (host = host_id )])
131
+
132
+ with mock .patch .object (
133
+ self .ovn_client , '_wait_for_port_bindings_host' ) as mock_wait :
134
+ mock_wait .return_value = db_port
135
+ self .ovn_client .update_lsp_host_info (context , db_port_no_host )
136
+
137
+ # Assert _wait_for_port_bindings_host was called
138
+ mock_wait .assert_called_once_with (context , port_id )
139
+
140
+ # Assert host_id was set
141
+ self .nb_idl .db_set .assert_called_once_with (
142
+ 'Logical_Switch_Port' , port_id ,
143
+ ('external_ids' , {constants .OVN_HOST_ID_EXT_ID_KEY : host_id }))
144
+
145
+ def test_update_lsp_host_info_up_retry_fail (self ):
146
+ context = mock .MagicMock ()
147
+ port_id = 'fake-port-id'
148
+ db_port_no_host = mock .Mock (
149
+ id = port_id , port_bindings = [mock .Mock (host = "" )])
150
+
151
+ with mock .patch .object (
152
+ self .ovn_client , '_wait_for_port_bindings_host' ) as mock_wait :
153
+ mock_wait .side_effect = RuntimeError ("boom" )
154
+ self .ovn_client .update_lsp_host_info (context , db_port_no_host )
155
+
156
+ # Assert _wait_for_port_bindings_host was called
157
+ mock_wait .assert_called_once_with (context , port_id )
158
+
159
+ # Assert host_id was NOT set
160
+ self .assertFalse (self .nb_idl .db_set .called )
161
+
117
162
def test_update_lsp_host_info_down (self ):
118
163
context = mock .MagicMock ()
119
164
port_id = 'fake-port-id'
@@ -125,6 +170,47 @@ def test_update_lsp_host_info_down(self):
125
170
'Logical_Switch_Port' , port_id , 'external_ids' ,
126
171
constants .OVN_HOST_ID_EXT_ID_KEY , if_exists = True )
127
172
173
+ @mock .patch .object (ml2_db , 'get_port' )
174
+ def test__wait_for_port_bindings_host (self , mock_get_port ):
175
+ context = mock .MagicMock ()
176
+ host_id = 'fake-binding-host-id'
177
+ port_id = 'fake-port-id'
178
+ db_port_no_host = mock .Mock (
179
+ id = port_id , port_bindings = [mock .Mock (host = "" )])
180
+ db_port = mock .Mock (
181
+ id = port_id , port_bindings = [mock .Mock (host = host_id )])
182
+
183
+ mock_get_port .side_effect = (db_port_no_host , db_port )
184
+
185
+ ret = self .ovn_client ._wait_for_port_bindings_host (
186
+ context , port_id )
187
+
188
+ self .assertEqual (ret , db_port )
189
+
190
+ expected_calls = [mock .call (context , port_id ),
191
+ mock .call (context , port_id )]
192
+ mock_get_port .assert_has_calls (expected_calls )
193
+
194
+ @mock .patch .object (ml2_db , 'get_port' )
195
+ def test__wait_for_port_bindings_host_fail (self , mock_get_port ):
196
+ context = mock .MagicMock ()
197
+ port_id = 'fake-port-id'
198
+ db_port_no_pb = mock .Mock (id = port_id , port_bindings = [])
199
+ db_port_no_host = mock .Mock (
200
+ id = port_id , port_bindings = [mock .Mock (host = "" )])
201
+
202
+ mock_get_port .side_effect = (
203
+ db_port_no_pb , db_port_no_host , db_port_no_host )
204
+
205
+ self .assertRaises (
206
+ RuntimeError , self .ovn_client ._wait_for_port_bindings_host ,
207
+ context , port_id )
208
+
209
+ expected_calls = [mock .call (context , port_id ),
210
+ mock .call (context , port_id ),
211
+ mock .call (context , port_id )]
212
+ mock_get_port .assert_has_calls (expected_calls )
213
+
128
214
129
215
class TestOVNClientFairMeter (TestOVNClientBase ,
130
216
test_log_driver .TestOVNDriverBase ):
0 commit comments