15
15
16
16
import abc
17
17
import copy
18
+ import functools
18
19
import inspect
19
20
import re
20
21
import threading
53
54
INCONSISTENCY_TYPE_DELETE = 'delete'
54
55
55
56
57
+ def has_lock_periodic (* args , ** kwargs ):
58
+ def wrapper (f ):
59
+ @functools .wraps (f )
60
+ @periodics .periodic (* args , ** kwargs )
61
+ def decorator (self , * args , ** kwargs ):
62
+ # This periodic task is included in DBInconsistenciesPeriodics
63
+ # since it uses the lock to ensure only one worker is executing
64
+ if not self .has_lock :
65
+ return
66
+ return f (self , * args , ** kwargs )
67
+ return decorator
68
+ return wrapper
69
+
70
+
56
71
class MaintenanceThread (object ):
57
72
58
73
def __init__ (self ):
@@ -289,15 +304,10 @@ def _fix_create_update_subnet(self, context, row):
289
304
# is held by some other neutron-server instance in the cloud, we'll attempt
290
305
# to perform the migration every 10 seconds until completed.
291
306
# TODO(ihrachys): Remove the migration to stateful fips in Z+1.
292
- @periodics . periodic (spacing = 10 , run_immediately = True )
307
+ @has_lock_periodic (spacing = 10 , run_immediately = True )
293
308
@rerun_on_schema_updates
294
309
def migrate_to_stateful_fips (self ):
295
310
"""Perform the migration from stateless to stateful Floating IPs. """
296
- # Only the worker holding a valid lock within OVSDB will perform the
297
- # migration.
298
- if not self .has_lock :
299
- return
300
-
301
311
admin_context = n_context .get_admin_context ()
302
312
nb_sync = ovn_db_sync .OvnNbSynchronizer (
303
313
self ._ovn_client ._plugin , self ._nb_idl , self ._ovn_client ._sb_idl ,
@@ -310,7 +320,7 @@ def migrate_to_stateful_fips(self):
310
320
# to perform the migration every 10 seconds until completed.
311
321
# TODO(jlibosva): Remove the migration to port groups at some point. It's
312
322
# been around since Queens release so it is good to drop this soon.
313
- @periodics . periodic (spacing = 10 , run_immediately = True )
323
+ @has_lock_periodic (spacing = 10 , run_immediately = True )
314
324
@rerun_on_schema_updates
315
325
def migrate_to_port_groups (self ):
316
326
"""Perform the migration from Address Sets to Port Groups. """
@@ -322,11 +332,6 @@ def migrate_to_port_groups(self):
322
332
if not self ._nb_idl .get_address_sets ():
323
333
raise periodics .NeverAgain ()
324
334
325
- # Only the worker holding a valid lock within OVSDB will perform the
326
- # migration.
327
- if not self .has_lock :
328
- return
329
-
330
335
admin_context = n_context .get_admin_context ()
331
336
nb_sync = ovn_db_sync .OvnNbSynchronizer (
332
337
self ._ovn_client ._plugin , self ._nb_idl , self ._ovn_client ._sb_idl ,
@@ -358,14 +363,9 @@ def _log(inconsistencies, type_):
358
363
_log (create_update_inconsistencies , INCONSISTENCY_TYPE_CREATE_UPDATE )
359
364
_log (delete_inconsistencies , INCONSISTENCY_TYPE_DELETE )
360
365
361
- @periodics . periodic (spacing = ovn_const .DB_CONSISTENCY_CHECK_INTERVAL ,
362
- run_immediately = True )
366
+ @has_lock_periodic (spacing = ovn_const .DB_CONSISTENCY_CHECK_INTERVAL ,
367
+ run_immediately = True )
363
368
def check_for_inconsistencies (self ):
364
- # Only the worker holding a valid lock within OVSDB will run
365
- # this periodic
366
- if not self .has_lock :
367
- return
368
-
369
369
admin_context = n_context .get_admin_context ()
370
370
create_update_inconsistencies = (
371
371
revision_numbers_db .get_inconsistent_resources (admin_context ))
@@ -481,13 +481,8 @@ def _delete_floatingip_and_pf(self, context, fip_id):
481
481
482
482
# A static spacing value is used here, but this method will only run
483
483
# once per lock due to the use of periodics.NeverAgain().
484
- @periodics .periodic (spacing = 600 ,
485
- run_immediately = True )
484
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
486
485
def check_global_dhcp_opts (self ):
487
- # This periodic task is included in DBInconsistenciesPeriodics since
488
- # it uses the lock to ensure only one worker is executing
489
- if not self .has_lock :
490
- return
491
486
if (not ovn_conf .get_global_dhcpv4_opts () and
492
487
not ovn_conf .get_global_dhcpv6_opts ()):
493
488
# No need to scan the subnets if the settings are unset.
@@ -516,11 +511,8 @@ def check_global_dhcp_opts(self):
516
511
517
512
# A static spacing value is used here, but this method will only run
518
513
# once per lock due to the use of periodics.NeverAgain().
519
- @periodics . periodic (spacing = 600 , run_immediately = True )
514
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
520
515
def check_for_igmp_snoop_support (self ):
521
- if not self .has_lock :
522
- return
523
-
524
516
with self ._nb_idl .transaction (check_error = True ) as txn :
525
517
value = ('true' if ovn_conf .is_igmp_snooping_enabled ()
526
518
else 'false' )
@@ -539,11 +531,8 @@ def check_for_igmp_snoop_support(self):
539
531
# TODO(czesla): Remove this in the A+4 cycle
540
532
# A static spacing value is used here, but this method will only run
541
533
# once per lock due to the use of periodics.NeverAgain().
542
- @periodics . periodic (spacing = 600 , run_immediately = True )
534
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
543
535
def check_port_has_address_scope (self ):
544
- if not self .has_lock :
545
- return
546
-
547
536
ports = self ._nb_idl .db_find_rows (
548
537
"Logical_Switch_Port" , ("type" , "!=" , ovn_const .LSP_TYPE_LOCALNET )
549
538
).execute (check_error = True )
@@ -585,16 +574,13 @@ def _delete_default_ha_chassis_group(self, txn):
585
574
586
575
# A static spacing value is used here, but this method will only run
587
576
# once per lock due to the use of periodics.NeverAgain().
588
- @periodics . periodic (spacing = 600 , run_immediately = True )
577
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
589
578
def check_for_ha_chassis_group (self ):
590
579
# If external ports is not supported stop running
591
580
# this periodic task
592
581
if not self ._ovn_client .is_external_ports_supported ():
593
582
raise periodics .NeverAgain ()
594
583
595
- if not self .has_lock :
596
- return
597
-
598
584
external_ports = self ._nb_idl .db_find_rows (
599
585
'Logical_Switch_Port' , ('type' , '=' , ovn_const .LSP_TYPE_EXTERNAL )
600
586
).execute (check_error = True )
@@ -618,11 +604,8 @@ def check_for_ha_chassis_group(self):
618
604
# TODO(lucasagomes): Remove this in the B+3 cycle
619
605
# A static spacing value is used here, but this method will only run
620
606
# once per lock due to the use of periodics.NeverAgain().
621
- @periodics . periodic (spacing = 600 , run_immediately = True )
607
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
622
608
def check_for_mcast_flood_reports (self ):
623
- if not self .has_lock :
624
- return
625
-
626
609
cmds = []
627
610
for port in self ._nb_idl .lsp_list ().execute (check_error = True ):
628
611
port_type = port .type .strip ()
@@ -667,11 +650,8 @@ def check_for_mcast_flood_reports(self):
667
650
# TODO(lucasagomes): Remove this in the Z cycle
668
651
# A static spacing value is used here, but this method will only run
669
652
# once per lock due to the use of periodics.NeverAgain().
670
- @periodics . periodic (spacing = 600 , run_immediately = True )
653
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
671
654
def check_router_mac_binding_options (self ):
672
- if not self .has_lock :
673
- return
674
-
675
655
cmds = []
676
656
for router in self ._nb_idl .lr_list ().execute (check_error = True ):
677
657
if (router .options .get ('always_learn_from_arp_request' ) and
@@ -692,16 +672,13 @@ def check_router_mac_binding_options(self):
692
672
# TODO(ralonsoh): Remove this in the Z+2 cycle
693
673
# A static spacing value is used here, but this method will only run
694
674
# once per lock due to the use of periodics.NeverAgain().
695
- @periodics . periodic (spacing = 600 , run_immediately = True )
675
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
696
676
def update_port_qos_with_external_ids_reference (self ):
697
677
"""Update all OVN QoS registers with the port ID
698
678
699
679
This method will only update the OVN QoS registers related to port QoS,
700
680
not FIP QoS. FIP QoS have the corresponding "external_ids" reference.
701
681
"""
702
- if not self .has_lock :
703
- return
704
-
705
682
regex = re .compile (
706
683
r'(inport|outport) == \"(?P<port_id>[a-z0-9\-]{36})\"' )
707
684
cmds = []
@@ -726,14 +703,12 @@ def update_port_qos_with_external_ids_reference(self):
726
703
727
704
# A static spacing value is used here, but this method will only run
728
705
# once per lock due to the use of periodics.NeverAgain().
729
- @periodics . periodic (spacing = 600 , run_immediately = True )
706
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
730
707
def check_redirect_type_router_gateway_ports (self ):
731
708
"""Check OVN router gateway ports
732
709
Check for the option "redirect-type=bridged" value for
733
710
router gateway ports.
734
711
"""
735
- if not self .has_lock :
736
- return
737
712
context = n_context .get_admin_context ()
738
713
cmds = []
739
714
gw_ports = self ._ovn_client ._plugin .get_ports (
@@ -786,14 +761,12 @@ def check_redirect_type_router_gateway_ports(self):
786
761
787
762
# A static spacing value is used here, but this method will only run
788
763
# once per lock due to the use of periodics.NeverAgain().
789
- @periodics . periodic (spacing = 600 , run_immediately = True )
764
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
790
765
def check_vlan_distributed_ports (self ):
791
766
"""Check VLAN distributed ports
792
767
Check for the option "reside-on-redirect-chassis" value for
793
768
distributed VLAN ports.
794
769
"""
795
- if not self .has_lock :
796
- return
797
770
context = n_context .get_admin_context ()
798
771
cmds = []
799
772
# Get router ports belonging to VLAN networks
@@ -829,12 +802,9 @@ def check_vlan_distributed_ports(self):
829
802
# a gateway (that means, that has "external_ids:OVN_GW_PORT_EXT_ID_KEY").
830
803
# A static spacing value is used here, but this method will only run
831
804
# once per lock due to the use of periodics.NeverAgain().
832
- @periodics . periodic (spacing = 600 , run_immediately = True )
805
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
833
806
def update_logical_router_with_gateway_network_id (self ):
834
807
"""Update all OVN logical router registers with the GW network ID"""
835
- if not self .has_lock :
836
- return
837
-
838
808
cmds = []
839
809
context = n_context .get_admin_context ()
840
810
for lr in self ._nb_idl .lr_list ().execute (check_error = True ):
@@ -859,7 +829,7 @@ def update_logical_router_with_gateway_network_id(self):
859
829
860
830
# A static spacing value is used here, but this method will only run
861
831
# once per lock due to the use of periodics.NeverAgain().
862
- @periodics . periodic (spacing = 600 , run_immediately = True )
832
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
863
833
def check_baremetal_ports_dhcp_options (self ):
864
834
"""Update baremetal ports DHCP options
865
835
@@ -871,9 +841,6 @@ def check_baremetal_ports_dhcp_options(self):
871
841
if not self ._ovn_client .is_external_ports_supported ():
872
842
raise periodics .NeverAgain ()
873
843
874
- if not self .has_lock :
875
- return
876
-
877
844
context = n_context .get_admin_context ()
878
845
ports = ports_obj .Port .get_ports_by_vnic_type_and_host (
879
846
context , portbindings .VNIC_BAREMETAL )
@@ -911,16 +878,13 @@ def check_baremetal_ports_dhcp_options(self):
911
878
raise periodics .NeverAgain ()
912
879
913
880
# TODO(ralonsoh): Remove this in the Z+4 cycle
914
- @periodics . periodic (spacing = 600 , run_immediately = True )
881
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
915
882
def update_port_virtual_type (self ):
916
883
"""Set type=virtual to those ports with parents
917
884
Before LP#1973276, any virtual port with "device_owner" defined, lost
918
885
its type=virtual. This task restores the type for those ports updated
919
886
before the fix https://review.opendev.org/c/openstack/neutron/+/841711.
920
887
"""
921
- if not self .has_lock :
922
- return
923
-
924
888
context = n_context .get_admin_context ()
925
889
cmds = []
926
890
for lsp in self ._nb_idl .lsp_list ().execute (check_error = True ):
@@ -948,7 +912,7 @@ def update_port_virtual_type(self):
948
912
raise periodics .NeverAgain ()
949
913
950
914
# TODO(ralonsoh): Remove this in the Antelope+4 cycle
951
- @periodics . periodic (spacing = 600 , run_immediately = True )
915
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
952
916
def create_router_extra_attributes_registers (self ):
953
917
"""Create missing ``RouterExtraAttributes`` registers.
954
918
@@ -958,9 +922,6 @@ def create_router_extra_attributes_registers(self):
958
922
only execution method finds those ``Routers`` registers without the
959
923
child one and creates one with the default values.
960
924
"""
961
- if not self .has_lock :
962
- return
963
-
964
925
context = n_context .get_admin_context ()
965
926
for router_id in router_obj .Router .\
966
927
get_router_ids_without_router_std_attrs (context ):
@@ -1008,13 +969,10 @@ def add_gw_port_info_to_logical_router_port(self):
1008
969
txn .add (cmd )
1009
970
raise periodics .NeverAgain ()
1010
971
1011
- @periodics . periodic (spacing = 600 , run_immediately = True )
972
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
1012
973
def check_router_default_route_empty_dst_ip (self ):
1013
974
"""Check routers with default route with empty dst-ip (LP: #2002993).
1014
975
"""
1015
- if not self .has_lock :
1016
- return
1017
-
1018
976
cmds = []
1019
977
for router in self ._nb_idl .lr_list ().execute (check_error = True ):
1020
978
if not router .external_ids .get (ovn_const .OVN_REV_NUM_EXT_ID_KEY ):
@@ -1036,7 +994,7 @@ def check_router_default_route_empty_dst_ip(self):
1036
994
raise periodics .NeverAgain ()
1037
995
1038
996
# TODO(ralonsoh): Remove this in the Antelope+4 cycle
1039
- @periodics . periodic (spacing = 600 , run_immediately = True )
997
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
1040
998
def add_vnic_type_and_pb_capabilities_to_lsp (self ):
1041
999
"""Add the port VNIC type and port binding capabilities to the LSP.
1042
1000
@@ -1047,9 +1005,6 @@ def add_vnic_type_and_pb_capabilities_to_lsp(self):
1047
1005
been added to the LSP the VNIC type and the port binding capabilities.
1048
1006
To implement LP#1998608, only direct ports are needed.
1049
1007
"""
1050
- if not self .has_lock :
1051
- return
1052
-
1053
1008
port_bindings = ports_obj .PortBinding .get_port_binding_by_vnic_type (
1054
1009
n_context .get_admin_context (), portbindings .VNIC_DIRECT )
1055
1010
with self ._nb_idl .transaction (check_error = True ) as txn :
@@ -1071,7 +1026,7 @@ def add_vnic_type_and_pb_capabilities_to_lsp(self):
1071
1026
1072
1027
raise periodics .NeverAgain ()
1073
1028
1074
- @periodics . periodic (spacing = 600 , run_immediately = True )
1029
+ @has_lock_periodic (spacing = 600 , run_immediately = True )
1075
1030
def check_fair_meter_consistency (self ):
1076
1031
"""Update the logging meter after neutron-server reload
1077
1032
@@ -1080,16 +1035,14 @@ def check_fair_meter_consistency(self):
1080
1035
driver after the OVN NB idl is loaded
1081
1036
1082
1037
"""
1083
- if not self .has_lock :
1084
- return
1085
1038
if log_driver .OVNDriver .network_logging_supported (self ._nb_idl ):
1086
1039
meter_name = (
1087
1040
cfg .CONF .network_log .local_output_log_base or "acl_log_meter" )
1088
1041
self ._ovn_client .create_ovn_fair_meter (meter_name ,
1089
1042
from_reload = True )
1090
1043
raise periodics .NeverAgain ()
1091
1044
1092
- @periodics . periodic (spacing = 300 , run_immediately = True )
1045
+ @has_lock_periodic (spacing = 300 , run_immediately = True )
1093
1046
def remove_duplicated_chassis_registers (self ):
1094
1047
"""Remove the "Chassis" and "Chassis_Private" duplicated registers.
1095
1048
@@ -1108,9 +1061,6 @@ def remove_duplicated_chassis_registers(self):
1108
1061
if not self ._sb_idl .is_table_present ('Chassis_Private' ):
1109
1062
raise periodics .NeverAgain ()
1110
1063
1111
- if not self .has_lock :
1112
- return
1113
-
1114
1064
# dup_chassis_port_host = {host_name: [(ch1, ch_private1),
1115
1065
# (ch2, ch_private2), ... ]}
1116
1066
dup_chassis_port_host = {}
@@ -1146,7 +1096,7 @@ def remove_duplicated_chassis_registers(self):
1146
1096
for table in ('Chassis_Private' , 'Chassis' ):
1147
1097
txn .add (self ._sb_idl .db_destroy (table , ch .name ))
1148
1098
1149
- @periodics . periodic (spacing = 86400 , run_immediately = True )
1099
+ @has_lock_periodic (spacing = 86400 , run_immediately = True )
1150
1100
def cleanup_old_hash_ring_nodes (self ):
1151
1101
"""Daily task to cleanup old stable Hash Ring node entries.
1152
1102
@@ -1155,8 +1105,6 @@ def cleanup_old_hash_ring_nodes(self):
1155
1105
information.
1156
1106
1157
1107
"""
1158
- if not self .has_lock :
1159
- return
1160
1108
context = n_context .get_admin_context ()
1161
1109
hash_ring_db .cleanup_old_nodes (context , days = 5 )
1162
1110
0 commit comments