OF port deletion complete implementation
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / confighelpers / ItmOfTunnelDeleteWorker.java
index b1ecc3b54eb587c36cd8c2105a29738a6e2f1e19..67578bf2aae8c98dff88cdcd51f45eb13b4630aa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
+ * Copyright (c) 2019 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 
 package org.opendaylight.genius.itm.confighelpers;
 
-import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
+import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+import org.opendaylight.genius.cloudscaler.api.TombstonedNodeManager;
+import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
+import org.opendaylight.genius.itm.cache.OfDpnTepConfigCache;
+import org.opendaylight.genius.itm.cache.OfTepStateCache;
+import org.opendaylight.genius.itm.cache.OvsBridgeEntryCache;
 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
+import org.opendaylight.genius.itm.impl.ITMBatchingUtils;
 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
-import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
 import org.opendaylight.mdsal.binding.api.DataBroker;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
+import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
+import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
+import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
+import org.opendaylight.mdsal.common.api.ReadFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.tep.config.OfDpnTep;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.of.teps.state.OfTep;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.OperationFailedException;
+import org.opendaylight.yangtools.yang.common.Uint64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class ItmOfTunnelDeleteWorker {
-    public ItmOfTunnelDeleteWorker(DataBroker dataBroker, JobCoordinator jobCoordinator, ItmConfig itmConfig,
-                                   DirectTunnelUtils directTunnelUtils, OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
-                                   DataTreeEventCallbackRegistrar eventCallbackRegistrar) {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ItmOfTunnelDeleteWorker.class);
+    private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
+
+    private final ManagedNewTransactionRunner txRunner;
+    private final DataBroker dataBroker;
+    private final OfDpnTepConfigCache ofDpnTepConfigCache;
+    private final TombstonedNodeManager tombstonedNodeManager;
+    private final IInterfaceManager interfaceManager;
+    private final DirectTunnelUtils directTunnelUtils;
+    private final OvsBridgeRefEntryCache ovsBridgeRefEntryCache;
+    private final OvsBridgeEntryCache ovsBridgeEntryCache;
+    private final OfTepStateCache ofTepStateCache;
+
+    public ItmOfTunnelDeleteWorker(DataBroker dataBroker,
+                                   OfDpnTepConfigCache ofDpnTepConfigCache,
+                                   TombstonedNodeManager tombstonedNodeManager,
+                                   IInterfaceManager interfaceManager,
+                                   DirectTunnelUtils directTunnelUtils,
+                                   OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
+                                   OvsBridgeEntryCache ovsBridgeEntryCache,
+                                   OfTepStateCache ofTepStateCache) {
+        this.dataBroker = dataBroker;
+        this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
+        this.ofDpnTepConfigCache = ofDpnTepConfigCache;
+        this.tombstonedNodeManager = tombstonedNodeManager;
+        this.interfaceManager = interfaceManager;
+        this.directTunnelUtils = directTunnelUtils;
+        this.ovsBridgeRefEntryCache = ovsBridgeRefEntryCache;
+        this.ovsBridgeEntryCache = ovsBridgeEntryCache;
+        this.ofTepStateCache = ofTepStateCache;
+    }
+
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    public List<? extends ListenableFuture<?>> deleteOfTeps(Collection<OfDpnTep> ofTepsList) {
+        LOG.trace("OFTeps to be deleted {} " , ofTepsList);
+        return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
+            if (ofTepsList == null || ofTepsList.size() == 0) {
+                LOG.debug("no ofteps to delete");
+                return;
+            }
+
+            for (OfDpnTep srcDpn : ofTepsList) {
+                LOG.trace("Processing srcDpn {}", srcDpn);
+
+                Boolean isDpnTombstoned = tombstonedNodeManager.isDpnTombstoned(srcDpn.getSourceDpnId());
+
+                removeOfTepInterfaceFromOvsdb(srcDpn, tx);
+                if (isDpnTombstoned) {
+                    EVENT_LOGGER.debug("OfTep-DeleteWorker, Tombstoned, DpnTep for {} removed",
+                            srcDpn.getSourceDpnId());
+                    LOG.trace("Removing tunnelState entry for {} while tombstoned is set true",srcDpn.getSourceDpnId());
+                    removeOfTepState(srcDpn);
+                }
+                LOG.debug("Deleting OFTEP Interface information from Config datastore with DPNs-Tep "
+                        + "for source Dpn {}", srcDpn.getSourceDpnId());
+                // Clean up the DPNs TEP State DS
+                DirectTunnelUtils.removeOfTepFromDpnsTepConfigDS(dataBroker, srcDpn.getSourceDpnId());
+                EVENT_LOGGER.debug("OfTep-DeleteWorker, DpnTep for {} removed", srcDpn.getSourceDpnId());
+            }
+        }));
+    }
+
+    private void removeOfTepState(OfDpnTep srcDpn) {
+        LOG.trace("Removing ofTepstate for {} with tomstoned enable", srcDpn.getOfPortName());
+        directTunnelUtils.deleteOfTepStateEntry(srcDpn.getOfPortName());
+    }
+
+    private void removeOfTepInterfaceFromOvsdb(OfDpnTep dpnTep, TypedReadWriteTransaction<Configuration> tx) {
+        LOG.trace("Removing ofTep Interface {}", dpnTep.getOfPortName());
+        try {
+            removeConfiguration(dpnTep, tx);
+        } catch (ExecutionException | InterruptedException | OperationFailedException e) {
+            LOG.error("Cannot Delete Tunnel {} as OVS Bridge Entry is NULL ", dpnTep.getTunnelType(), e);
+        }
+    }
+
+    private void removeConfiguration(OfDpnTep dpnsTep, TypedReadWriteTransaction<Configuration> tx)
+            throws ExecutionException, InterruptedException, OperationFailedException {
+        // Check if the same transaction can be used across Config and operational shards
+        removeTunnelConfiguration(dpnsTep, tx);
+    }
+
+    private void removeTunnelConfiguration(OfDpnTep dpnTep, TypedReadWriteTransaction<Configuration> tx)
+            throws ExecutionException, InterruptedException, OperationFailedException {
+
+        LOG.info("removing ofTep configuration for {}", dpnTep.getOfPortName());
+
+        Optional<OvsBridgeRefEntry> ovsBridgeRefEntry = ovsBridgeRefEntryCache.get(dpnTep.getSourceDpnId());
+        Optional<OvsBridgeEntry> ovsBridgeEntryOptional;
+        OvsdbBridgeRef ovsdbBridgeRef = null;
+        if (ovsBridgeRefEntry.isPresent()) {
+            ovsdbBridgeRef = ovsBridgeRefEntry.get().getOvsBridgeReference();
+        } else {
+            ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpnTep.getSourceDpnId());
+            if (ovsBridgeEntryOptional.isPresent()) {
+                ovsdbBridgeRef = ovsBridgeEntryOptional.get().getOvsBridgeReference();
+            }
+        }
+
+        if (ovsdbBridgeRef != null) {
+            removeTerminationEndPoint(ovsdbBridgeRef.getValue(), dpnTep.getOfPortName());
+        }
+
+        // delete tunnel ingress flow
+        removeOfPortIngressFlow(tx, dpnTep.getOfPortName(), dpnTep.getSourceDpnId());
+
+        // delete bridge to tunnel interface mappings
+        OvsBridgeEntryKey bridgeEntryKey = new OvsBridgeEntryKey(dpnTep.getSourceDpnId());
+        InstanceIdentifier<OvsBridgeEntry> bridgeEntryIid =
+                DirectTunnelUtils.getOvsBridgeEntryIdentifier(bridgeEntryKey);
+
+        ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpnTep.getSourceDpnId());
+        if (ovsBridgeEntryOptional.isPresent()) {
+            Map<OvsBridgeTunnelEntryKey, OvsBridgeTunnelEntry> bridgeTunnelEntries = ovsBridgeEntryOptional
+                    .get().getOvsBridgeTunnelEntry();
+            deleteBridgeInterfaceEntry(bridgeEntryKey,
+                    bridgeTunnelEntries.values().stream().collect(Collectors.toList()),
+                    bridgeEntryIid, dpnTep.getOfPortName());
+            // IfIndex needs to be removed only during State Clean up not Config
+            cleanUpOfTepWithUnknownState(dpnTep.getOfPortName(), tx);
+            directTunnelUtils.removeLportTagInterfaceMap(dpnTep.getOfPortName());
+        }
+    }
+
+    private void removeTerminationEndPoint(InstanceIdentifier<?> bridgeIid, String ofPortName) {
+        LOG.debug("removing termination point for {}", ofPortName);
+        InstanceIdentifier<TerminationPoint> tpIid = DirectTunnelUtils.createTerminationPointInstanceIdentifier(
+                InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), ofPortName);
+        ITMBatchingUtils.delete(tpIid, ITMBatchingUtils.EntityType.TOPOLOGY_CONFIG);
+    }
+
+    private void removeOfPortIngressFlow(TypedReadWriteTransaction<Configuration> tx,
+                                         String ofTepName,
+                                         Uint64 dpId) throws ExecutionException, InterruptedException {
+        directTunnelUtils.removeTunnelIngressFlow(tx, dpId, ofTepName);
+    }
+
+    private void deleteBridgeInterfaceEntry(OvsBridgeEntryKey bridgeEntryKey,
+                                            List<OvsBridgeTunnelEntry> bridgeTunnelEntries,
+                                            InstanceIdentifier<OvsBridgeEntry> bridgeEntryIid,
+                                            String ofTepName) {
+        OvsBridgeTunnelEntryKey bridgeTunnelEntryKey = new OvsBridgeTunnelEntryKey(ofTepName);
+        InstanceIdentifier<OvsBridgeTunnelEntry> bridgeTunnelEntryIid =
+                DirectTunnelUtils.getBridgeTunnelEntryIdentifier(bridgeEntryKey, bridgeTunnelEntryKey);
+        ITMBatchingUtils.delete(bridgeTunnelEntryIid, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
+        if (bridgeTunnelEntries.size() <= 1) {
+            ITMBatchingUtils.delete(bridgeEntryIid, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
+        }
+    }
+
+    // if the node is shutdown, there will be stale ofTep state entries,
+    // with unknown op-state, clear them.
+    private void cleanUpOfTepWithUnknownState(String ofTepName, TypedReadWriteTransaction<Configuration> tx)
+            throws ReadFailedException {
+        Optional<OfTep> ofTepList = ofTepStateCache.get(ofTepName);
+        if (ofTepList.isPresent() && ofTepList.get().getOfTepState() == TunnelOperStatus.Unknown) {
+            LOG.debug("cleaning up dpnTep for {}, since the oper-status is {}", ofTepName,
+                    ofTepList.get().getOfTepState());
+            directTunnelUtils.deleteOfTepStateEntry(ofTepName);
+        }
     }
+
 }