OF port deletion complete implementation
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / confighelpers / ItmOfTunnelDeleteWorker.java
1 /*
2  * Copyright (c) 2019 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.genius.itm.confighelpers;
10
11 import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
12
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Optional;
19 import java.util.concurrent.ExecutionException;
20 import java.util.stream.Collectors;
21 import org.opendaylight.genius.cloudscaler.api.TombstonedNodeManager;
22 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
23 import org.opendaylight.genius.itm.cache.OfDpnTepConfigCache;
24 import org.opendaylight.genius.itm.cache.OfTepStateCache;
25 import org.opendaylight.genius.itm.cache.OvsBridgeEntryCache;
26 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
27 import org.opendaylight.genius.itm.impl.ITMBatchingUtils;
28 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
29 import org.opendaylight.mdsal.binding.api.DataBroker;
30 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
31 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
32 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
33 import org.opendaylight.mdsal.binding.util.TypedReadWriteTransaction;
34 import org.opendaylight.mdsal.common.api.ReadFailedException;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntry;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.OvsBridgeEntryKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntry;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.bridge.tunnel.info.ovs.bridge.entry.OvsBridgeTunnelEntryKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.ovs.bridge.ref.info.OvsBridgeRefEntry;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.tep.config.OfDpnTep;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.of.teps.state.OfTep;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
46 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
47 import org.opendaylight.yangtools.yang.common.OperationFailedException;
48 import org.opendaylight.yangtools.yang.common.Uint64;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 public class ItmOfTunnelDeleteWorker {
53
54     private static final Logger LOG = LoggerFactory.getLogger(ItmOfTunnelDeleteWorker.class);
55     private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
56
57     private final ManagedNewTransactionRunner txRunner;
58     private final DataBroker dataBroker;
59     private final OfDpnTepConfigCache ofDpnTepConfigCache;
60     private final TombstonedNodeManager tombstonedNodeManager;
61     private final IInterfaceManager interfaceManager;
62     private final DirectTunnelUtils directTunnelUtils;
63     private final OvsBridgeRefEntryCache ovsBridgeRefEntryCache;
64     private final OvsBridgeEntryCache ovsBridgeEntryCache;
65     private final OfTepStateCache ofTepStateCache;
66
67     public ItmOfTunnelDeleteWorker(DataBroker dataBroker,
68                                    OfDpnTepConfigCache ofDpnTepConfigCache,
69                                    TombstonedNodeManager tombstonedNodeManager,
70                                    IInterfaceManager interfaceManager,
71                                    DirectTunnelUtils directTunnelUtils,
72                                    OvsBridgeRefEntryCache ovsBridgeRefEntryCache,
73                                    OvsBridgeEntryCache ovsBridgeEntryCache,
74                                    OfTepStateCache ofTepStateCache) {
75         this.dataBroker = dataBroker;
76         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
77         this.ofDpnTepConfigCache = ofDpnTepConfigCache;
78         this.tombstonedNodeManager = tombstonedNodeManager;
79         this.interfaceManager = interfaceManager;
80         this.directTunnelUtils = directTunnelUtils;
81         this.ovsBridgeRefEntryCache = ovsBridgeRefEntryCache;
82         this.ovsBridgeEntryCache = ovsBridgeEntryCache;
83         this.ofTepStateCache = ofTepStateCache;
84     }
85
86     @SuppressWarnings("checkstyle:IllegalCatch")
87     public List<? extends ListenableFuture<?>> deleteOfTeps(Collection<OfDpnTep> ofTepsList) {
88         LOG.trace("OFTeps to be deleted {} " , ofTepsList);
89         return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
90             if (ofTepsList == null || ofTepsList.size() == 0) {
91                 LOG.debug("no ofteps to delete");
92                 return;
93             }
94
95             for (OfDpnTep srcDpn : ofTepsList) {
96                 LOG.trace("Processing srcDpn {}", srcDpn);
97
98                 Boolean isDpnTombstoned = tombstonedNodeManager.isDpnTombstoned(srcDpn.getSourceDpnId());
99
100                 removeOfTepInterfaceFromOvsdb(srcDpn, tx);
101                 if (isDpnTombstoned) {
102                     EVENT_LOGGER.debug("OfTep-DeleteWorker, Tombstoned, DpnTep for {} removed",
103                             srcDpn.getSourceDpnId());
104                     LOG.trace("Removing tunnelState entry for {} while tombstoned is set true",srcDpn.getSourceDpnId());
105                     removeOfTepState(srcDpn);
106                 }
107                 LOG.debug("Deleting OFTEP Interface information from Config datastore with DPNs-Tep "
108                         + "for source Dpn {}", srcDpn.getSourceDpnId());
109                 // Clean up the DPNs TEP State DS
110                 DirectTunnelUtils.removeOfTepFromDpnsTepConfigDS(dataBroker, srcDpn.getSourceDpnId());
111                 EVENT_LOGGER.debug("OfTep-DeleteWorker, DpnTep for {} removed", srcDpn.getSourceDpnId());
112             }
113         }));
114     }
115
116     private void removeOfTepState(OfDpnTep srcDpn) {
117         LOG.trace("Removing ofTepstate for {} with tomstoned enable", srcDpn.getOfPortName());
118         directTunnelUtils.deleteOfTepStateEntry(srcDpn.getOfPortName());
119     }
120
121     private void removeOfTepInterfaceFromOvsdb(OfDpnTep dpnTep, TypedReadWriteTransaction<Configuration> tx) {
122         LOG.trace("Removing ofTep Interface {}", dpnTep.getOfPortName());
123         try {
124             removeConfiguration(dpnTep, tx);
125         } catch (ExecutionException | InterruptedException | OperationFailedException e) {
126             LOG.error("Cannot Delete Tunnel {} as OVS Bridge Entry is NULL ", dpnTep.getTunnelType(), e);
127         }
128     }
129
130     private void removeConfiguration(OfDpnTep dpnsTep, TypedReadWriteTransaction<Configuration> tx)
131             throws ExecutionException, InterruptedException, OperationFailedException {
132         // Check if the same transaction can be used across Config and operational shards
133         removeTunnelConfiguration(dpnsTep, tx);
134     }
135
136     private void removeTunnelConfiguration(OfDpnTep dpnTep, TypedReadWriteTransaction<Configuration> tx)
137             throws ExecutionException, InterruptedException, OperationFailedException {
138
139         LOG.info("removing ofTep configuration for {}", dpnTep.getOfPortName());
140
141         Optional<OvsBridgeRefEntry> ovsBridgeRefEntry = ovsBridgeRefEntryCache.get(dpnTep.getSourceDpnId());
142         Optional<OvsBridgeEntry> ovsBridgeEntryOptional;
143         OvsdbBridgeRef ovsdbBridgeRef = null;
144         if (ovsBridgeRefEntry.isPresent()) {
145             ovsdbBridgeRef = ovsBridgeRefEntry.get().getOvsBridgeReference();
146         } else {
147             ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpnTep.getSourceDpnId());
148             if (ovsBridgeEntryOptional.isPresent()) {
149                 ovsdbBridgeRef = ovsBridgeEntryOptional.get().getOvsBridgeReference();
150             }
151         }
152
153         if (ovsdbBridgeRef != null) {
154             removeTerminationEndPoint(ovsdbBridgeRef.getValue(), dpnTep.getOfPortName());
155         }
156
157         // delete tunnel ingress flow
158         removeOfPortIngressFlow(tx, dpnTep.getOfPortName(), dpnTep.getSourceDpnId());
159
160         // delete bridge to tunnel interface mappings
161         OvsBridgeEntryKey bridgeEntryKey = new OvsBridgeEntryKey(dpnTep.getSourceDpnId());
162         InstanceIdentifier<OvsBridgeEntry> bridgeEntryIid =
163                 DirectTunnelUtils.getOvsBridgeEntryIdentifier(bridgeEntryKey);
164
165         ovsBridgeEntryOptional = ovsBridgeEntryCache.get(dpnTep.getSourceDpnId());
166         if (ovsBridgeEntryOptional.isPresent()) {
167             Map<OvsBridgeTunnelEntryKey, OvsBridgeTunnelEntry> bridgeTunnelEntries = ovsBridgeEntryOptional
168                     .get().getOvsBridgeTunnelEntry();
169             deleteBridgeInterfaceEntry(bridgeEntryKey,
170                     bridgeTunnelEntries.values().stream().collect(Collectors.toList()),
171                     bridgeEntryIid, dpnTep.getOfPortName());
172             // IfIndex needs to be removed only during State Clean up not Config
173             cleanUpOfTepWithUnknownState(dpnTep.getOfPortName(), tx);
174             directTunnelUtils.removeLportTagInterfaceMap(dpnTep.getOfPortName());
175         }
176     }
177
178     private void removeTerminationEndPoint(InstanceIdentifier<?> bridgeIid, String ofPortName) {
179         LOG.debug("removing termination point for {}", ofPortName);
180         InstanceIdentifier<TerminationPoint> tpIid = DirectTunnelUtils.createTerminationPointInstanceIdentifier(
181                 InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), ofPortName);
182         ITMBatchingUtils.delete(tpIid, ITMBatchingUtils.EntityType.TOPOLOGY_CONFIG);
183     }
184
185     private void removeOfPortIngressFlow(TypedReadWriteTransaction<Configuration> tx,
186                                          String ofTepName,
187                                          Uint64 dpId) throws ExecutionException, InterruptedException {
188         directTunnelUtils.removeTunnelIngressFlow(tx, dpId, ofTepName);
189     }
190
191     private void deleteBridgeInterfaceEntry(OvsBridgeEntryKey bridgeEntryKey,
192                                             List<OvsBridgeTunnelEntry> bridgeTunnelEntries,
193                                             InstanceIdentifier<OvsBridgeEntry> bridgeEntryIid,
194                                             String ofTepName) {
195         OvsBridgeTunnelEntryKey bridgeTunnelEntryKey = new OvsBridgeTunnelEntryKey(ofTepName);
196         InstanceIdentifier<OvsBridgeTunnelEntry> bridgeTunnelEntryIid =
197                 DirectTunnelUtils.getBridgeTunnelEntryIdentifier(bridgeEntryKey, bridgeTunnelEntryKey);
198         ITMBatchingUtils.delete(bridgeTunnelEntryIid, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
199         if (bridgeTunnelEntries.size() <= 1) {
200             ITMBatchingUtils.delete(bridgeEntryIid, ITMBatchingUtils.EntityType.DEFAULT_CONFIG);
201         }
202     }
203
204     // if the node is shutdown, there will be stale ofTep state entries,
205     // with unknown op-state, clear them.
206     private void cleanUpOfTepWithUnknownState(String ofTepName, TypedReadWriteTransaction<Configuration> tx)
207             throws ReadFailedException {
208         Optional<OfTep> ofTepList = ofTepStateCache.get(ofTepName);
209         if (ofTepList.isPresent() && ofTepList.get().getOfTepState() == TunnelOperStatus.Unknown) {
210             LOG.debug("cleaning up dpnTep for {}, since the oper-status is {}", ofTepName,
211                     ofTepList.get().getOfTepState());
212             directTunnelUtils.deleteOfTepStateEntry(ofTepName);
213         }
214     }
215
216 }