13
13
# under the License.
14
14
15
15
import abc
16
+ import copy
17
+ import uuid
16
18
17
19
from oslo_utils import timeutils
20
+ from ovs .db import idl as ovs_idl
18
21
from ovsdbapp .backend .ovs_idl import command
19
22
from ovsdbapp .backend .ovs_idl import idlutils
23
+ from ovsdbapp .backend .ovs_idl import rowview
20
24
from ovsdbapp .schema .ovn_northbound import commands as ovn_nb_commands
21
25
from ovsdbapp import utils as ovsdbapp_utils
22
26
@@ -100,6 +104,49 @@ def _add_gateway_chassis(api, txn, lrp_name, val):
100
104
return 'gateway_chassis' , uuid_list
101
105
102
106
107
+ def _sync_ha_chassis_group (txn , nb_api , name , chassis_priority ,
108
+ may_exist = False , table_name = 'HA_Chassis_Group' ,
109
+ ** columns ):
110
+ result = None
111
+ hcg = nb_api .lookup (table_name , name , default = None )
112
+ if hcg :
113
+ if not may_exist :
114
+ raise RuntimeError (_ ('HA_Chassis_Group %s exists' % name ))
115
+ else :
116
+ hcg = txn .insert (nb_api ._tables [table_name ])
117
+ hcg .name = name
118
+ command .BaseCommand .set_columns (hcg , ** columns )
119
+ result = hcg .uuid
120
+
121
+ # HA_Chassis registers handling.
122
+ # Remove the non-existing chassis in ``self.chassis_priority``
123
+ hc_to_remove = []
124
+ for hc in getattr (hcg , 'ha_chassis' , []):
125
+ if hc .chassis_name not in chassis_priority :
126
+ hc_to_remove .append (hc )
127
+
128
+ for hc in hc_to_remove :
129
+ hcg .delvalue ('ha_chassis' , hc )
130
+ hc .delete ()
131
+
132
+ # Update the priority of the existing chassis.
133
+ for hc in getattr (hcg , 'ha_chassis' , []):
134
+ hc_priority = chassis_priority .pop (hc .chassis_name )
135
+ hc .priority = hc_priority
136
+
137
+ # Add the non-existing HA_Chassis registers.
138
+ for hc_name , priority in chassis_priority .items ():
139
+ hc = txn .insert (nb_api .tables ['HA_Chassis' ])
140
+ hc .chassis_name = hc_name
141
+ hc .priority = priority
142
+ hcg .addvalue ('ha_chassis' , hc )
143
+
144
+ if not result :
145
+ result = rowview .RowView (hcg )
146
+
147
+ return result
148
+
149
+
103
150
class CheckLivenessCommand (command .BaseCommand ):
104
151
def run_idl (self , txn ):
105
152
# txn.pre_commit responsible for updating nb_global.nb_cfg, but
@@ -110,21 +157,64 @@ def run_idl(self, txn):
110
157
self .result = self .api .nb_global .nb_cfg
111
158
112
159
160
+ class AddNetworkCommand (command .AddCommand ):
161
+ table_name = 'Logical_Switch'
162
+
163
+ def __init__ (self , api , network_id , may_exist = False , ** columns ):
164
+ super ().__init__ (api )
165
+ self .network_uuid = uuid .UUID (str (network_id ))
166
+ self .may_exist = may_exist
167
+ self .columns = columns
168
+
169
+ def run_idl (self , txn ):
170
+ table = self .api .tables [self .table_name ]
171
+ try :
172
+ ls = table .rows [self .network_uuid ]
173
+ if self .may_exist :
174
+ self .result = rowview .RowView (ls )
175
+ return
176
+ msg = _ ("Switch %s already exists" ) % self .network_uuid
177
+ raise RuntimeError (msg )
178
+ except KeyError :
179
+ # Adding a new LS
180
+ if utils .ovs_persist_uuid_supported (txn .idl ):
181
+ ls = txn .insert (table , new_uuid = self .network_uuid ,
182
+ persist_uuid = True )
183
+ else :
184
+ ls = txn .insert (table )
185
+ self .set_columns (ls , ** self .columns )
186
+ ls .name = utils .ovn_name (self .network_uuid )
187
+ self .result = ls .uuid
188
+
189
+
113
190
class AddLSwitchPortCommand (command .BaseCommand ):
114
- def __init__ (self , api , lport , lswitch , may_exist , ** columns ):
191
+ def __init__ (self , api , lport , lswitch , may_exist , network_id = None ,
192
+ ** columns ):
115
193
super ().__init__ (api )
116
194
self .lport = lport
117
195
self .lswitch = lswitch
118
196
self .may_exist = may_exist
197
+ self .network_uuid = uuid .UUID (str (network_id )) if network_id else None
119
198
self .columns = columns
120
199
121
200
def run_idl (self , txn ):
122
201
try :
202
+ # We must look in the local cache first, because the LS may have
203
+ # been created as part of the current transaction. or in the case
204
+ # of adding an LSP to a LS that was created before persist_uuid
123
205
lswitch = idlutils .row_by_value (self .api .idl , 'Logical_Switch' ,
124
206
'name' , self .lswitch )
125
207
except idlutils .RowNotFound :
126
- msg = _ ("Logical Switch %s does not exist" ) % self .lswitch
127
- raise RuntimeError (msg )
208
+ if self .network_uuid and utils .ovs_persist_uuid_supported (txn .idl ):
209
+ # Create a "fake" row with the right UUID so python-ovs creates
210
+ # a transaction referencing the Row, even though we might not
211
+ # have received the update for the row ourselves.
212
+ lswitch = ovs_idl .Row (self .api .idl ,
213
+ self .api .tables ['Logical_Switch' ],
214
+ uuid = self .network_uuid , data = {})
215
+ else :
216
+ msg = _ ("Logical Switch %s does not exist" ) % self .lswitch
217
+ raise RuntimeError (msg )
128
218
if self .may_exist :
129
219
port = idlutils .row_by_value (self .api .idl ,
130
220
'Logical_Switch_Port' , 'name' ,
@@ -210,8 +300,8 @@ def run_idl(self, txn):
210
300
else :
211
301
new_port_dhcp_opts .add (dhcpv6_options .result )
212
302
port .dhcpv6_options = [dhcpv6_options .result ]
213
- for uuid in cur_port_dhcp_opts - new_port_dhcp_opts :
214
- self .api ._tables ['DHCP_Options' ].rows [uuid ].delete ()
303
+ for uuid_ in cur_port_dhcp_opts - new_port_dhcp_opts :
304
+ self .api ._tables ['DHCP_Options' ].rows [uuid_ ].delete ()
215
305
216
306
external_ids_update = self .external_ids_update or {}
217
307
external_ids = getattr (port , 'external_ids' , {})
@@ -293,8 +383,8 @@ def run_idl(self, txn):
293
383
# Delete DHCP_Options records no longer referred by this port.
294
384
cur_port_dhcp_opts = get_lsp_dhcp_options_uuids (
295
385
lport , self .lport )
296
- for uuid in cur_port_dhcp_opts :
297
- self .api ._tables ['DHCP_Options' ].rows [uuid ].delete ()
386
+ for uuid_ in cur_port_dhcp_opts :
387
+ self .api ._tables ['DHCP_Options' ].rows [uuid_ ].delete ()
298
388
299
389
_delvalue_from_list (lswitch , 'ports' , lport )
300
390
self .api ._tables ['Logical_Switch_Port' ].rows [lport .uuid ].delete ()
@@ -347,8 +437,7 @@ def run_idl(self, txn):
347
437
az_hints = self .api .get_gateway_chassis_az_hints (self .g_name )
348
438
filtered_existing_chassis = (
349
439
self .scheduler .filter_existing_chassis (
350
- nb_idl = self .api , gw_chassis = self .all_gw_chassis ,
351
- physnet = physnet ,
440
+ gw_chassis = self .all_gw_chassis , physnet = physnet ,
352
441
chassis_physnets = self .chassis_with_physnets ,
353
442
existing_chassis = existing_chassis , az_hints = az_hints ,
354
443
chassis_with_azs = self .chassis_with_azs ))
@@ -388,9 +477,12 @@ def run_idl(self, txn):
388
477
# the top.
389
478
index = chassis .index (primary )
390
479
chassis [0 ], chassis [index ] = chassis [index ], chassis [0 ]
391
- setattr (
392
- lrouter_port ,
393
- * _add_gateway_chassis (self .api , txn , self .g_name , chassis ))
480
+ chassis_priority = utils .get_chassis_priority (chassis )
481
+ lrouter_name = lrouter_port .external_ids [
482
+ ovn_const .OVN_ROUTER_NAME_EXT_ID_KEY ]
483
+ hcg = _sync_ha_chassis_group (txn , self .api , lrouter_name ,
484
+ chassis_priority , may_exist = True )
485
+ setattr (lrouter_port , 'ha_chassis_group' , ovsdbapp_utils .get_uuid (hcg ))
394
486
395
487
396
488
class ScheduleNewGatewayCommand (command .BaseCommand ):
@@ -415,8 +507,11 @@ def run_idl(self, txn):
415
507
self .api , self .sb_api , self .g_name , candidates = candidates ,
416
508
target_lrouter = lrouter )
417
509
if chassis :
418
- setattr (lrouter_port ,
419
- * _add_gateway_chassis (self .api , txn , self .g_name , chassis ))
510
+ chassis_priority = utils .get_chassis_priority (chassis )
511
+ hcg = _sync_ha_chassis_group (txn , self .api , self .lrouter_name ,
512
+ chassis_priority , may_exist = True )
513
+ setattr (lrouter_port , 'ha_chassis_group' ,
514
+ ovsdbapp_utils .get_uuid (hcg ))
420
515
421
516
422
517
class LrDelCommand (ovn_nb_commands .LrDelCommand ):
@@ -465,8 +560,9 @@ def run_idl(self, txn):
465
560
if col == 'gateway_chassis' :
466
561
col , val = _add_gateway_chassis (self .api , txn , self .name ,
467
562
val )
468
- setattr (lrouter_port , col , val )
563
+ self . set_column (lrouter_port , col , val )
469
564
_addvalue_to_list (lrouter , 'ports' , lrouter_port )
565
+ self .result = lrouter_port .uuid
470
566
471
567
472
568
class UpdateLRouterPortCommand (command .BaseCommand ):
@@ -491,7 +587,7 @@ def run_idl(self, txn):
491
587
if col == 'gateway_chassis' :
492
588
col , val = _add_gateway_chassis (self .api , txn , self .name ,
493
589
val )
494
- setattr (lrouter_port , col , val )
590
+ self . set_column (lrouter_port , col , val )
495
591
496
592
497
593
class DelLRouterPortCommand (command .BaseCommand ):
@@ -1008,15 +1104,17 @@ def run_idl(self, txn):
1008
1104
# Remove the router pinning to a chassis (if any).
1009
1105
lrouter .delkey ('options' , 'chassis' )
1010
1106
1011
- # Remove the HA_Chassis_Group of the router (if any).
1107
+ for gw_port in self .api .get_lrouter_gw_ports (lrouter .name ):
1108
+ gw_port .ha_chassis_group = []
1109
+ lrouter .delvalue ('ports' , gw_port )
1110
+
1111
+ # Remove the HA_Chassis_Group of the router (if any), after
1112
+ # removing it from the gateway Logical_Router_Ports.
1012
1113
hcg = self .api .lookup ('HA_Chassis_Group' ,
1013
1114
lrouter .name , default = None )
1014
1115
if hcg :
1015
1116
hcg .delete ()
1016
1117
1017
- for gw_port in self .api .get_lrouter_gw_ports (lrouter .name ):
1018
- lrouter .delvalue ('ports' , gw_port )
1019
-
1020
1118
1021
1119
class SetLSwitchPortToVirtualTypeCommand (command .BaseCommand ):
1022
1120
def __init__ (self , api , lport , vip , parent , if_exists ):
@@ -1089,3 +1187,22 @@ def run_idl(self, txn):
1089
1187
virtual_parents )
1090
1188
1091
1189
setattr (lsp , 'options' , options )
1190
+
1191
+
1192
+ class HAChassisGroupWithHCAddCommand (command .AddCommand ):
1193
+ table_name = 'HA_Chassis_Group'
1194
+
1195
+ def __init__ (self , api , name , chassis_priority , may_exist = False ,
1196
+ ** columns ):
1197
+ super ().__init__ (api )
1198
+ self .name = name
1199
+ self .chassis_priority = copy .deepcopy (chassis_priority )
1200
+ self .may_exist = may_exist
1201
+ self .columns = columns
1202
+
1203
+ def run_idl (self , txn ):
1204
+ # HA_Chassis_Group register creation.
1205
+ self .result = _sync_ha_chassis_group (
1206
+ txn , self .api , self .name , self .chassis_priority ,
1207
+ may_exist = self .may_exist , table_name = self .table_name ,
1208
+ ** self .columns )
0 commit comments