def check_global_dhcp_opts(self): # This periodic task is included in DBInconsistenciesPeriodics since # it uses the lock to ensure only one worker is executing if not self.has_lock: return if (not ovn_conf.get_global_dhcpv4_opts() and not ovn_conf.get_global_dhcpv6_opts()): # No need to scan the subnets if the settings are unset. raise periodics.NeverAgain() LOG.debug('Maintenance task: Checking DHCP options on subnets') self._sync_timer.restart() fix_subnets = self._check_subnet_global_dhcp_opts() if fix_subnets: admin_context = n_context.get_admin_context() LOG.debug('Triggering update for %s subnets', len(fix_subnets)) for subnet in fix_subnets: neutron_net = self._ovn_client._plugin.get_network( admin_context, subnet['network_id']) try: self._ovn_client.update_subnet(admin_context, subnet, neutron_net) except Exception: LOG.exception('Failed to update subnet %s', subnet['id']) self._sync_timer.stop() LOG.info('Maintenance task: DHCP options check finished ' '(took %.2f seconds)', self._sync_timer.elapsed()) raise periodics.NeverAgain()
def check_for_ha_chassis_group(self): # If external ports is not supported stop running # this periodic task if not self._ovn_client.is_external_ports_supported(): raise periodics.NeverAgain() if not self.has_lock: return external_ports = self._nb_idl.db_find_rows( 'Logical_Switch_Port', ('type', '=', ovn_const.LSP_TYPE_EXTERNAL) ).execute(check_error=True) context = n_context.get_admin_context() with self._nb_idl.transaction(check_error=True) as txn: for port in external_ports: network_id = port.external_ids[ ovn_const.OVN_NETWORK_NAME_EXT_ID_KEY].replace( ovn_const.OVN_NAME_PREFIX, '') ha_ch_grp = self._ovn_client.sync_ha_chassis_group( context, network_id, txn) try: port_ha_ch_uuid = port.ha_chassis_group[0].uuid except IndexError: port_ha_ch_uuid = None if port_ha_ch_uuid != ha_ch_grp: txn.add(self._nb_idl.set_lswitch_port( port.name, ha_chassis_group=ha_ch_grp)) self._delete_default_ha_chassis_group(txn) raise periodics.NeverAgain()
def check_for_ha_chassis_group_address(self): # If external ports is not supported stop running # this periodic task if not self._ovn_client.is_external_ports_supported(): raise periodics.NeverAgain() if not self.has_lock: return default_ch_grp = self._nb_idl.ha_chassis_group_add( ovn_const.HA_CHASSIS_GROUP_DEFAULT_NAME, may_exist=True).execute(check_error=True) # NOTE(lucasagomes): Find the existing chassis with the highest # priority and keep it as being the highest to avoid moving # things around high_prio_ch = max(default_ch_grp.ha_chassis, key=lambda x: x.priority, default=None) all_ch = self._sb_idl.get_all_chassis() gw_ch = self._sb_idl.get_gateway_chassis_from_cms_options() ch_to_del = set(all_ch) - set(gw_ch) with self._nb_idl.transaction(check_error=True) as txn: for ch in ch_to_del: txn.add( self._nb_idl.ha_chassis_group_del_chassis( ovn_const.HA_CHASSIS_GROUP_DEFAULT_NAME, ch, if_exists=True)) # NOTE(lucasagomes): If the high priority chassis is in # the list of chassis to be added/updated. Add it first with # the highest priority number possible and then add the rest # (the priority of the rest of the chassis does not matter # since only the highest one is active) priority = ovn_const.HA_CHASSIS_GROUP_HIGHEST_PRIORITY if high_prio_ch and high_prio_ch.chassis_name in gw_ch: txn.add( self._nb_idl.ha_chassis_group_add_chassis( ovn_const.HA_CHASSIS_GROUP_DEFAULT_NAME, high_prio_ch.chassis_name, priority=priority)) gw_ch.remove(high_prio_ch.chassis_name) priority -= 1 for ch in gw_ch: txn.add( self._nb_idl.ha_chassis_group_add_chassis( ovn_const.HA_CHASSIS_GROUP_DEFAULT_NAME, ch, priority=priority)) priority -= 1 raise periodics.NeverAgain()
def check_metadata_ports(self): # If OVN metadata is disabled do not run this task again if not ovn_conf.is_ovn_metadata_enabled(): raise periodics.NeverAgain() # Make sure that only one worker is executing this if not self.has_lock: return admin_context = n_context.get_admin_context() for n in self._ovn_client._plugin.get_networks(admin_context): self._ovn_client.create_metadata_port(admin_context, n) raise periodics.NeverAgain()
def check_baremetal_ports_dhcp_options(self): """Update baremetal ports DHCP options Update baremetal ports DHCP options based on the "disable_ovn_dhcp_for_baremetal_ports" configuration option. """ # If external ports is not supported stop running # this periodic task if not self._ovn_client.is_external_ports_supported(): raise periodics.NeverAgain() if not self.has_lock: return context = n_context.get_admin_context() ports = self._ovn_client._plugin.get_ports( context, filters={portbindings.VNIC_TYPE: portbindings.VNIC_BAREMETAL}) if not ports: raise periodics.NeverAgain() with self._nb_idl.transaction(check_error=True) as txn: for port in ports: lsp = self._nb_idl.lsp_get(port['id']).execute( check_error=True) if not lsp: continue update_dhcp = False if ovn_conf.is_ovn_dhcp_disabled_for_baremetal(): if lsp.dhcpv4_options or lsp.dhcpv6_options: update_dhcp = True else: if not lsp.dhcpv4_options and not lsp.dhcpv6_options: update_dhcp = True if update_dhcp: port_info = self._ovn_client._get_port_options(port) dhcpv4_options, dhcpv6_options = ( self._ovn_client.update_port_dhcp_options( port_info, txn)) txn.add(self._nb_idl.set_lswitch_port( lport_name=port['id'], dhcpv4_options=dhcpv4_options, dhcpv6_options=dhcpv6_options, if_exists=False)) raise periodics.NeverAgain()
def migrate_to_stateless_fips(self): """Perform the migration from stateful to stateless Floating IPs. """ if not self._ovn_client.is_stateless_nat_supported(): raise periodics.NeverAgain() # Only the worker holding a valid lock within OVSDB will perform the # migration. if not self.has_lock: return admin_context = n_context.get_admin_context() nb_sync = ovn_db_sync.OvnNbSynchronizer( self._ovn_client._plugin, self._nb_idl, self._ovn_client._sb_idl, None, None) nb_sync.migrate_to_stateless_fips(admin_context) raise periodics.NeverAgain()
def periodic_sync_task(): try: self.sync(ironic) except InvalidFilterDriverState as e: LOG.warning('Filter driver %s disabling periodic sync ' 'task because of an invalid state.', self) raise periodics.NeverAgain(e)
def check_for_port_security_unknown_address(self): if not self.has_lock: return for port in self._nb_idl.lsp_list().execute(check_error=True): if port.type == ovn_const.LSP_TYPE_LOCALNET: continue addresses = port.addresses type_ = port.type.strip() if not port.port_security: if not type_ and ovn_const.UNKNOWN_ADDR not in addresses: addresses.append(ovn_const.UNKNOWN_ADDR) elif type_ and ovn_const.UNKNOWN_ADDR in addresses: addresses.remove(ovn_const.UNKNOWN_ADDR) else: if type_ and ovn_const.UNKNOWN_ADDR in addresses: addresses.remove(ovn_const.UNKNOWN_ADDR) elif not type_ and ovn_const.UNKNOWN_ADDR in addresses: addresses.remove(ovn_const.UNKNOWN_ADDR) if addresses: self._nb_idl.lsp_set_addresses( port.name, addresses=addresses).execute(check_error=True) else: self._nb_idl.db_clear('Logical_Switch_Port', port.name, 'addresses').execute(check_error=True) raise periodics.NeverAgain()
def update_logical_router_with_gateway_network_id(self): """Update all OVN logical router registers with the GW network ID""" if not self.has_lock: return cmds = [] context = n_context.get_admin_context() for lr in self._nb_idl.lr_list().execute(check_error=True): gw_port = lr.external_ids.get(ovn_const.OVN_GW_PORT_EXT_ID_KEY) gw_net = lr.external_ids.get(ovn_const.OVN_GW_NETWORK_EXT_ID_KEY) if not gw_port or (gw_port and gw_net): # This router does not have a gateway network assigned yet or # it has a gateway port and its corresponding network. continue port = self._ovn_client._plugin.get_port(context, gw_port) external_ids = { ovn_const.OVN_GW_NETWORK_EXT_ID_KEY: port['network_id']} cmds.append(self._nb_idl.db_set( 'Logical_Router', lr.uuid, ('external_ids', external_ids))) if cmds: with self._nb_idl.transaction(check_error=True) as txn: for cmd in cmds: txn.add(cmd) raise periodics.NeverAgain()
def check_vlan_distributed_ports(self): """Check VLAN distributed ports Check for the option "reside-on-redirect-chassis" value for distributed VLAN ports. """ if not self.has_lock: return context = n_context.get_admin_context() cmds = [] # Get router ports belonging to VLAN networks vlan_nets = self._ovn_client._plugin.get_networks( context, {pnet.NETWORK_TYPE: [n_const.TYPE_VLAN]}) vlan_net_ids = [vn['id'] for vn in vlan_nets] router_ports = self._ovn_client._plugin.get_ports( context, {'network_id': vlan_net_ids, 'device_owner': n_const.ROUTER_PORT_OWNERS}) expected_value = ('false' if ovn_conf.is_ovn_distributed_floating_ip() else 'true') for rp in router_ports: lrp_name = utils.ovn_lrouter_port_name(rp['id']) lrp = self._nb_idl.get_lrouter_port(lrp_name) if lrp.options.get( ovn_const.LRP_OPTIONS_RESIDE_REDIR_CH) != expected_value: opt = {ovn_const.LRP_OPTIONS_RESIDE_REDIR_CH: expected_value} cmds.append(self._nb_idl.db_set( 'Logical_Router_Port', lrp_name, ('options', opt))) if cmds: with self._nb_idl.transaction(check_error=True) as txn: for cmd in cmds: txn.add(cmd) raise periodics.NeverAgain()
def check_for_localnet_legacy_port_name(self): if not self.has_lock: return admin_context = n_context.get_admin_context() cmds = [] for ls in self._nb_idl.ls_list().execute(check_error=True): network_id = ls.name.replace('neutron-', '') legacy_name = utils.ovn_provnet_port_name(network_id) legacy_port = None segment_id = None for lsp in ls.ports: if legacy_name == lsp.name: legacy_port = lsp break else: continue for segment in segments_db.get_network_segments( admin_context, network_id): if (segment.get(segment_def.PHYSICAL_NETWORK) == legacy_port.options['network_name']): segment_id = segment['id'] break if not segment_id: continue new_p_name = utils.ovn_provnet_port_name(segment_id) cmds.append( self._nb_idl.db_set('Logical_Switch_Port', legacy_port.uuid, ('name', new_p_name))) if cmds: with self._nb_idl.transaction(check_error=True) as txn: for cmd in cmds: txn.add(cmd) raise periodics.NeverAgain()
def check_for_mcast_flood_reports(self): if not self.has_lock: return cmds = [] for port in self._nb_idl.lsp_list().execute(check_error=True): port_type = port.type.strip() if port_type in ("vtep", ovn_const.LSP_TYPE_LOCALPORT, "router"): continue options = port.options if port_type == ovn_const.LSP_TYPE_LOCALNET: mcast_flood_value = options.get( ovn_const.LSP_OPTIONS_MCAST_FLOOD_REPORTS) if mcast_flood_value == 'false': continue options.update({ovn_const.LSP_OPTIONS_MCAST_FLOOD: 'false'}) elif ovn_const.LSP_OPTIONS_MCAST_FLOOD_REPORTS in options: continue options.update({ovn_const.LSP_OPTIONS_MCAST_FLOOD_REPORTS: 'true'}) cmds.append(self._nb_idl.lsp_set_options(port.name, **options)) if cmds: with self._nb_idl.transaction(check_error=True) as txn: for cmd in cmds: txn.add(cmd) raise periodics.NeverAgain()
def update_port_qos_with_external_ids_reference(self): """Update all OVN QoS registers with the port ID This method will only update the OVN QoS registers related to port QoS, not FIP QoS. FIP QoS have the corresponding "external_ids" reference. """ if not self.has_lock: return regex = re.compile( r'(inport|outport) == \"(?P<port_id>[a-z0-9\-]{36})\"') cmds = [] for ls in self._nb_idl.ls_list().execute(check_error=True): for qos in self._nb_idl.qos_list(ls.name).execute( check_error=True): if qos.external_ids: continue match = re.match(regex, qos.match) if not match: continue port_id = match.group('port_id') external_ids = {ovn_const.OVN_PORT_EXT_ID_KEY: port_id} cmds.append(self._nb_idl.db_set( 'QoS', qos.uuid, ('external_ids', external_ids))) if cmds: with self._nb_idl.transaction(check_error=True) as txn: for cmd in cmds: txn.add(cmd) raise periodics.NeverAgain()
def check_for_fragmentation_support(self): if not self.has_lock: return context = n_context.get_admin_context() for net in self._ovn_client._plugin.get_networks( context, {external_net.EXTERNAL: [True]}): self._ovn_client.set_gateway_mtu(context, net) raise periodics.NeverAgain()
def periodic_sync_task(): nonlocal _cached_client if _cached_client is None: _cached_client = ir_utils.get_client() try: self.sync(_cached_client) except InvalidFilterDriverState as e: LOG.warning( 'Filter driver %s disabling periodic sync ' 'task because of an invalid state.', self) raise periodics.NeverAgain(e)
def migrate_to_port_groups(self): """Perform the migration from Address Sets to Port Groups. """ # TODO(dalvarez): Remove this in U cycle when we're sure that all # versions are running using Port Groups (and OVS >= 2.10). # If Port Groups are not supported or we've already migrated, we don't # need to attempt to migrate again. if not self._nb_idl.get_address_sets(): raise periodics.NeverAgain() # Only the worker holding a valid lock within OVSDB will perform the # migration. if not self.has_lock: return admin_context = n_context.get_admin_context() nb_sync = ovn_db_sync.OvnNbSynchronizer( self._ovn_client._plugin, self._nb_idl, self._ovn_client._sb_idl, None, None) nb_sync.migrate_to_port_groups(admin_context) raise periodics.NeverAgain()
def check_for_igmp_snoop_support(self): if not self.has_lock: return with self._nb_idl.transaction(check_error=True) as txn: value = ('true' if ovn_conf.is_igmp_snooping_enabled() else 'false') for ls in self._nb_idl.ls_list().execute(check_error=True): if ls.other_config.get(ovn_const.MCAST_SNOOP, None) == value: continue txn.add(self._nb_idl.db_set( 'Logical_Switch', ls.name, ('other_config', { ovn_const.MCAST_SNOOP: value, ovn_const.MCAST_FLOOD_UNREGISTERED: value}))) raise periodics.NeverAgain()
def check_for_port_security_unknown_address(self): if not self.has_lock: return for port in self._nb_idl.lsp_list().execute(check_error=True): addresses = port.addresses if not port.port_security and 'unknown' not in addresses: addresses.append('unknown') elif port.port_security and 'unknown' in addresses: addresses.remove('unknown') else: continue self._nb_idl.lsp_set_addresses( port.name, addresses=addresses).execute(check_error=True) raise periodics.NeverAgain()
def check_router_mac_binding_options(self): if not self.has_lock: return cmds = [] for router in self._nb_idl.lr_list().execute(check_error=True): if (router.options.get('always_learn_from_arp_request') and router.options.get('dynamic_neigh_routers')): continue opts = copy.deepcopy(router.options) opts.update({'always_learn_from_arp_request': 'false', 'dynamic_neigh_routers': 'true'}) cmds.append(self._nb_idl.update_lrouter(router.name, options=opts)) if cmds: with self._nb_idl.transaction(check_error=True) as txn: for cmd in cmds: txn.add(cmd) raise periodics.NeverAgain()
def run_only_once(): raise periodics.NeverAgain("No need to run again !!")
def run_only_once(started_at): print("1: %s" % (time.time() - started_at)) raise periodics.NeverAgain("No need to run again after first run !!")
def run_for_some_time(started_at): print("2: %s" % (time.time() - started_at)) if (time.time() - started_at) > 5: raise periodics.NeverAgain("No need to run again !!")