1515
1616import abc
1717import copy
18+ import functools
1819import inspect
1920import re
2021import threading
5354INCONSISTENCY_TYPE_DELETE = 'delete'
5455
5556
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+
5671class MaintenanceThread (object ):
5772
5873 def __init__ (self ):
@@ -289,15 +304,10 @@ def _fix_create_update_subnet(self, context, row):
289304 # is held by some other neutron-server instance in the cloud, we'll attempt
290305 # to perform the migration every 10 seconds until completed.
291306 # 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 )
293308 @rerun_on_schema_updates
294309 def migrate_to_stateful_fips (self ):
295310 """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-
301311 admin_context = n_context .get_admin_context ()
302312 nb_sync = ovn_db_sync .OvnNbSynchronizer (
303313 self ._ovn_client ._plugin , self ._nb_idl , self ._ovn_client ._sb_idl ,
@@ -358,14 +368,9 @@ def _log(inconsistencies, type_):
358368 _log (create_update_inconsistencies , INCONSISTENCY_TYPE_CREATE_UPDATE )
359369 _log (delete_inconsistencies , INCONSISTENCY_TYPE_DELETE )
360370
361- @periodics . periodic (spacing = ovn_const .DB_CONSISTENCY_CHECK_INTERVAL ,
362- run_immediately = True )
371+ @has_lock_periodic (spacing = ovn_const .DB_CONSISTENCY_CHECK_INTERVAL ,
372+ run_immediately = True )
363373 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-
369374 admin_context = n_context .get_admin_context ()
370375 create_update_inconsistencies = (
371376 revision_numbers_db .get_inconsistent_resources (admin_context ))
@@ -481,13 +486,8 @@ def _delete_floatingip_and_pf(self, context, fip_id):
481486
482487 # A static spacing value is used here, but this method will only run
483488 # once per lock due to the use of periodics.NeverAgain().
484- @periodics .periodic (spacing = 600 ,
485- run_immediately = True )
489+ @has_lock_periodic (spacing = 600 , run_immediately = True )
486490 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
491491 if (not ovn_conf .get_global_dhcpv4_opts () and
492492 not ovn_conf .get_global_dhcpv6_opts ()):
493493 # No need to scan the subnets if the settings are unset.
@@ -516,11 +516,8 @@ def check_global_dhcp_opts(self):
516516
517517 # A static spacing value is used here, but this method will only run
518518 # once per lock due to the use of periodics.NeverAgain().
519- @periodics . periodic (spacing = 600 , run_immediately = True )
519+ @has_lock_periodic (spacing = 600 , run_immediately = True )
520520 def check_for_igmp_snoop_support (self ):
521- if not self .has_lock :
522- return
523-
524521 with self ._nb_idl .transaction (check_error = True ) as txn :
525522 value = ('true' if ovn_conf .is_igmp_snooping_enabled ()
526523 else 'false' )
@@ -539,11 +536,8 @@ def check_for_igmp_snoop_support(self):
539536 # TODO(czesla): Remove this in the A+4 cycle
540537 # A static spacing value is used here, but this method will only run
541538 # once per lock due to the use of periodics.NeverAgain().
542- @periodics . periodic (spacing = 600 , run_immediately = True )
539+ @has_lock_periodic (spacing = 600 , run_immediately = True )
543540 def check_port_has_address_scope (self ):
544- if not self .has_lock :
545- return
546-
547541 ports = self ._nb_idl .db_find_rows (
548542 "Logical_Switch_Port" , ("type" , "!=" , ovn_const .LSP_TYPE_LOCALNET )
549543 ).execute (check_error = True )
@@ -618,11 +612,8 @@ def check_for_ha_chassis_group(self):
618612 # TODO(lucasagomes): Remove this in the B+3 cycle
619613 # A static spacing value is used here, but this method will only run
620614 # once per lock due to the use of periodics.NeverAgain().
621- @periodics . periodic (spacing = 600 , run_immediately = True )
615+ @has_lock_periodic (spacing = 600 , run_immediately = True )
622616 def check_for_mcast_flood_reports (self ):
623- if not self .has_lock :
624- return
625-
626617 cmds = []
627618 for port in self ._nb_idl .lsp_list ().execute (check_error = True ):
628619 port_type = port .type .strip ()
@@ -667,11 +658,8 @@ def check_for_mcast_flood_reports(self):
667658 # TODO(lucasagomes): Remove this in the Z cycle
668659 # A static spacing value is used here, but this method will only run
669660 # once per lock due to the use of periodics.NeverAgain().
670- @periodics . periodic (spacing = 600 , run_immediately = True )
661+ @has_lock_periodic (spacing = 600 , run_immediately = True )
671662 def check_router_mac_binding_options (self ):
672- if not self .has_lock :
673- return
674-
675663 cmds = []
676664 for router in self ._nb_idl .lr_list ().execute (check_error = True ):
677665 if (router .options .get ('always_learn_from_arp_request' ) and
@@ -726,14 +714,12 @@ def update_port_qos_with_external_ids_reference(self):
726714
727715 # A static spacing value is used here, but this method will only run
728716 # once per lock due to the use of periodics.NeverAgain().
729- @periodics . periodic (spacing = 600 , run_immediately = True )
717+ @has_lock_periodic (spacing = 600 , run_immediately = True )
730718 def check_redirect_type_router_gateway_ports (self ):
731719 """Check OVN router gateway ports
732720 Check for the option "redirect-type=bridged" value for
733721 router gateway ports.
734722 """
735- if not self .has_lock :
736- return
737723 context = n_context .get_admin_context ()
738724 cmds = []
739725 gw_ports = self ._ovn_client ._plugin .get_ports (
@@ -786,14 +772,12 @@ def check_redirect_type_router_gateway_ports(self):
786772
787773 # A static spacing value is used here, but this method will only run
788774 # once per lock due to the use of periodics.NeverAgain().
789- @periodics . periodic (spacing = 600 , run_immediately = True )
775+ @has_lock_periodic (spacing = 600 , run_immediately = True )
790776 def check_vlan_distributed_ports (self ):
791777 """Check VLAN distributed ports
792778 Check for the option "reside-on-redirect-chassis" value for
793779 distributed VLAN ports.
794780 """
795- if not self .has_lock :
796- return
797781 context = n_context .get_admin_context ()
798782 cmds = []
799783 # Get router ports belonging to VLAN networks
@@ -829,12 +813,9 @@ def check_vlan_distributed_ports(self):
829813 # a gateway (that means, that has "external_ids:OVN_GW_PORT_EXT_ID_KEY").
830814 # A static spacing value is used here, but this method will only run
831815 # once per lock due to the use of periodics.NeverAgain().
832- @periodics . periodic (spacing = 600 , run_immediately = True )
816+ @has_lock_periodic (spacing = 600 , run_immediately = True )
833817 def update_logical_router_with_gateway_network_id (self ):
834818 """Update all OVN logical router registers with the GW network ID"""
835- if not self .has_lock :
836- return
837-
838819 cmds = []
839820 context = n_context .get_admin_context ()
840821 for lr in self ._nb_idl .lr_list ().execute (check_error = True ):
@@ -911,16 +892,13 @@ def check_baremetal_ports_dhcp_options(self):
911892 raise periodics .NeverAgain ()
912893
913894 # TODO(ralonsoh): Remove this in the Z+4 cycle
914- @periodics . periodic (spacing = 600 , run_immediately = True )
895+ @has_lock_periodic (spacing = 600 , run_immediately = True )
915896 def update_port_virtual_type (self ):
916897 """Set type=virtual to those ports with parents
917898 Before LP#1973276, any virtual port with "device_owner" defined, lost
918899 its type=virtual. This task restores the type for those ports updated
919900 before the fix https://review.opendev.org/c/openstack/neutron/+/841711.
920901 """
921- if not self .has_lock :
922- return
923-
924902 context = n_context .get_admin_context ()
925903 cmds = []
926904 for lsp in self ._nb_idl .lsp_list ().execute (check_error = True ):
@@ -948,7 +926,7 @@ def update_port_virtual_type(self):
948926 raise periodics .NeverAgain ()
949927
950928 # TODO(ralonsoh): Remove this in the Antelope+4 cycle
951- @periodics . periodic (spacing = 600 , run_immediately = True )
929+ @has_lock_periodic (spacing = 600 , run_immediately = True )
952930 def create_router_extra_attributes_registers (self ):
953931 """Create missing ``RouterExtraAttributes`` registers.
954932
@@ -958,9 +936,6 @@ def create_router_extra_attributes_registers(self):
958936 only execution method finds those ``Routers`` registers without the
959937 child one and creates one with the default values.
960938 """
961- if not self .has_lock :
962- return
963-
964939 context = n_context .get_admin_context ()
965940 for router_id in router_obj .Router .\
966941 get_router_ids_without_router_std_attrs (context ):
@@ -1008,13 +983,10 @@ def add_gw_port_info_to_logical_router_port(self):
1008983 txn .add (cmd )
1009984 raise periodics .NeverAgain ()
1010985
1011- @periodics . periodic (spacing = 600 , run_immediately = True )
986+ @has_lock_periodic (spacing = 600 , run_immediately = True )
1012987 def check_router_default_route_empty_dst_ip (self ):
1013988 """Check routers with default route with empty dst-ip (LP: #2002993).
1014989 """
1015- if not self .has_lock :
1016- return
1017-
1018990 cmds = []
1019991 for router in self ._nb_idl .lr_list ().execute (check_error = True ):
1020992 if not router .external_ids .get (ovn_const .OVN_REV_NUM_EXT_ID_KEY ):
@@ -1036,7 +1008,7 @@ def check_router_default_route_empty_dst_ip(self):
10361008 raise periodics .NeverAgain ()
10371009
10381010 # TODO(ralonsoh): Remove this in the Antelope+4 cycle
1039- @periodics . periodic (spacing = 600 , run_immediately = True )
1011+ @has_lock_periodic (spacing = 600 , run_immediately = True )
10401012 def add_vnic_type_and_pb_capabilities_to_lsp (self ):
10411013 """Add the port VNIC type and port binding capabilities to the LSP.
10421014
@@ -1047,9 +1019,6 @@ def add_vnic_type_and_pb_capabilities_to_lsp(self):
10471019 been added to the LSP the VNIC type and the port binding capabilities.
10481020 To implement LP#1998608, only direct ports are needed.
10491021 """
1050- if not self .has_lock :
1051- return
1052-
10531022 port_bindings = ports_obj .PortBinding .get_port_binding_by_vnic_type (
10541023 n_context .get_admin_context (), portbindings .VNIC_DIRECT )
10551024 with self ._nb_idl .transaction (check_error = True ) as txn :
@@ -1071,7 +1040,7 @@ def add_vnic_type_and_pb_capabilities_to_lsp(self):
10711040
10721041 raise periodics .NeverAgain ()
10731042
1074- @periodics . periodic (spacing = 600 , run_immediately = True )
1043+ @has_lock_periodic (spacing = 600 , run_immediately = True )
10751044 def check_fair_meter_consistency (self ):
10761045 """Update the logging meter after neutron-server reload
10771046
@@ -1080,8 +1049,6 @@ def check_fair_meter_consistency(self):
10801049 driver after the OVN NB idl is loaded
10811050
10821051 """
1083- if not self .has_lock :
1084- return
10851052 if log_driver .OVNDriver .network_logging_supported (self ._nb_idl ):
10861053 meter_name = (
10871054 cfg .CONF .network_log .local_output_log_base or "acl_log_meter" )
@@ -1146,7 +1113,7 @@ def remove_duplicated_chassis_registers(self):
11461113 for table in ('Chassis_Private' , 'Chassis' ):
11471114 txn .add (self ._sb_idl .db_destroy (table , ch .name ))
11481115
1149- @periodics . periodic (spacing = 86400 , run_immediately = True )
1116+ @has_lock_periodic (spacing = 86400 , run_immediately = True )
11501117 def cleanup_old_hash_ring_nodes (self ):
11511118 """Daily task to cleanup old stable Hash Ring node entries.
11521119
@@ -1155,8 +1122,6 @@ def cleanup_old_hash_ring_nodes(self):
11551122 information.
11561123
11571124 """
1158- if not self .has_lock :
1159- return
11601125 context = n_context .get_admin_context ()
11611126 hash_ring_db .cleanup_old_nodes (context , days = 5 )
11621127
0 commit comments