Fix: Internal tunnels missing after karaf restart in all 3 CICs
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / cache / DPNTEPsInfoCache.java
1 /*
2  * Copyright (c) 2017 Inocybe Technologies 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 package org.opendaylight.genius.itm.cache;
9
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import java.util.List;
13 import java.util.Optional;
14 import javax.inject.Inject;
15 import javax.inject.Singleton;
16 import org.opendaylight.genius.itm.globals.ITMConstants;
17 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
18 import org.opendaylight.genius.itm.itmdirecttunnels.workers.TunnelStateAddWorker;
19 import org.opendaylight.genius.itm.itmdirecttunnels.workers.TunnelStateAddWorkerForNodeConnector;
20 import org.opendaylight.genius.itm.utils.TunnelEndPointInfo;
21 import org.opendaylight.genius.itm.utils.TunnelStateInfo;
22 import org.opendaylight.genius.itm.utils.TunnelStateInfoBuilder;
23 import org.opendaylight.genius.mdsalutil.cache.InstanceIdDataObjectCache;
24 import org.opendaylight.infrautils.caches.CacheProvider;
25 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
26 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.Acquired;
27 import org.opendaylight.mdsal.binding.api.DataBroker;
28 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
29 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
30 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
31 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.opendaylight.yangtools.yang.common.Uint64;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * Caches DPNTEPsInfo objects.
41  *
42  * @author Thomas Pantelis
43  */
44 @SuppressWarnings("checkstyle:AbbreviationAsWordInName")
45 @Singleton
46 public class DPNTEPsInfoCache extends InstanceIdDataObjectCache<DPNTEPsInfo> {
47
48     private static final Logger LOG = LoggerFactory.getLogger(DPNTEPsInfoCache.class);
49     private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
50
51     private final DirectTunnelUtils directTunnelUtils;
52     private final JobCoordinator coordinator;
53     private final UnprocessedNodeConnectorEndPointCache unprocessedNodeConnectorEndPointCache;
54     private final ManagedNewTransactionRunner txRunner;
55
56     @Inject
57     public DPNTEPsInfoCache(final DataBroker dataBroker, final CacheProvider cacheProvider,
58                             final DirectTunnelUtils directTunnelUtils, final JobCoordinator coordinator,
59                             final UnprocessedNodeConnectorEndPointCache unprocessedNodeConnectorEndPointCache) {
60         super(DPNTEPsInfo.class, dataBroker, LogicalDatastoreType.CONFIGURATION, cacheProvider);
61         this.directTunnelUtils = directTunnelUtils;
62         this.coordinator = coordinator;
63         this.unprocessedNodeConnectorEndPointCache = unprocessedNodeConnectorEndPointCache;
64         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
65         listenerRegistration = dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create(
66                 LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(DpnEndpoints.class)
67                 .child(DPNTEPsInfo.class).build()), dataObjectListener);
68     }
69
70     @Override
71     protected void added(InstanceIdentifier<DPNTEPsInfo> path, DPNTEPsInfo dpnTepsInfo) {
72         LOG.info("DPNTepsInfo Add Received for {}", dpnTepsInfo.getDPNID());
73         String dpnId = dpnTepsInfo.getDPNID().toString();
74
75         Collection<TunnelStateInfo> tunnelStateInfoList;
76         try (Acquired lock = directTunnelUtils.lockTunnel(dpnId)) {
77             tunnelStateInfoList = unprocessedNodeConnectorEndPointCache.remove(dpnId);
78         }
79
80         if (tunnelStateInfoList != null) {
81             for (TunnelStateInfo tsInfo : tunnelStateInfoList) {
82                 String interfaceName = tsInfo.getDpnTepInterfaceInfo().getTunnelName();
83                 DPNTEPsInfo srcDpnTepsInfo = null;
84                 DPNTEPsInfo dstDpnTepsInfo = null;
85                 LOG.debug("Processing the Unprocessed NodeConnector EndPoint Cache for DPN {}", dpnTepsInfo.getDPNID());
86                 TunnelEndPointInfo tunnelEndPointInfo = tsInfo.getTunnelEndPointInfo();
87                 if (dpnId.equals(tunnelEndPointInfo.getSrcEndPointInfo())) {
88                     srcDpnTepsInfo = dpnTepsInfo;
89                     dstDpnTepsInfo = tsInfo.getDstDpnTepsInfo();
90                     if (dstDpnTepsInfo == null) {
91                         // Check if the destination End Point has come
92                         try (Acquired lock = directTunnelUtils.lockTunnel(tunnelEndPointInfo.getDstEndPointInfo())) {
93                             Optional<DPNTEPsInfo> dstInfoOpt = getDPNTepFromDPNId(
94                                     Uint64.valueOf(tunnelEndPointInfo.getDstEndPointInfo()));
95                             if (dstInfoOpt.isPresent()) {
96                                 dstDpnTepsInfo = dstInfoOpt.get();
97                             } else {
98                                 TunnelStateInfo tunnelStateInfoNew = new TunnelStateInfoBuilder()
99                                     .setNodeConnectorInfo(tsInfo.getNodeConnectorInfo())
100                                     .setDpnTepInterfaceInfo(tsInfo.getDpnTepInterfaceInfo())
101                                     .setTunnelEndPointInfo(tsInfo.getTunnelEndPointInfo())
102                                     .setSrcDpnTepsInfo(srcDpnTepsInfo).build();
103                                 LOG.trace("Destination DPNTepsInfo is null for tunnel {}. Hence Parking with key {}",
104                                         interfaceName, tunnelEndPointInfo.getDstEndPointInfo());
105                                 unprocessedNodeConnectorEndPointCache.add(tunnelEndPointInfo
106                                         .getDstEndPointInfo(), tunnelStateInfoNew);
107                             }
108                         }
109                     }
110                 } else if (dpnId.equals(tunnelEndPointInfo.getDstEndPointInfo())) {
111                     dstDpnTepsInfo = dpnTepsInfo;
112                     srcDpnTepsInfo = tsInfo.getSrcDpnTepsInfo();
113                     // Check if the destination End Point has come
114                     if (srcDpnTepsInfo == null) {
115                         try (Acquired lock = directTunnelUtils.lockTunnel(tunnelEndPointInfo.getSrcEndPointInfo())) {
116                             Optional<DPNTEPsInfo> srcInfoOpt = getDPNTepFromDPNId(
117                                     Uint64.valueOf(tunnelEndPointInfo.getSrcEndPointInfo()));
118                             if (srcInfoOpt.isPresent()) {
119                                 srcDpnTepsInfo = srcInfoOpt.get();
120                             } else {
121                                 TunnelStateInfo tunnelStateInfoNew = new TunnelStateInfoBuilder().setNodeConnectorInfo(
122                                     tsInfo.getNodeConnectorInfo())
123                                     .setDpnTepInterfaceInfo(tsInfo.getDpnTepInterfaceInfo())
124                                     .setTunnelEndPointInfo(tsInfo.getTunnelEndPointInfo())
125                                     .setDstDpnTepsInfo(dstDpnTepsInfo).build();
126                                 LOG.trace("Source DPNTepsInfo is null for tunnel {}. Hence Parking with key {}",
127                                         interfaceName,
128                                         tsInfo.getTunnelEndPointInfo().getSrcEndPointInfo());
129                                 unprocessedNodeConnectorEndPointCache.add(tunnelEndPointInfo.getSrcEndPointInfo(),
130                                         tunnelStateInfoNew);
131                             }
132                         }
133                     }
134                 }
135
136                 if (srcDpnTepsInfo != null && dstDpnTepsInfo != null && directTunnelUtils.isEntityOwner()) {
137                     TunnelStateInfo tunnelStateInfoNew = new TunnelStateInfoBuilder()
138                         .setNodeConnectorInfo(tsInfo.getNodeConnectorInfo())
139                         .setDpnTepInterfaceInfo(tsInfo.getDpnTepInterfaceInfo())
140                         .setTunnelEndPointInfo(tsInfo.getTunnelEndPointInfo())
141                         .setSrcDpnTepsInfo(srcDpnTepsInfo).setDstDpnTepsInfo(dstDpnTepsInfo).build();
142                     LOG.debug("Queueing TunnelStateAddWorker to DJC for tunnel {}", interfaceName);
143                     EVENT_LOGGER.debug("ITM-DpnTepsInfoCache,ADD {}", interfaceName);
144                     coordinator.enqueueJob(interfaceName,
145                         new TunnelStateAddWorkerForNodeConnector(new TunnelStateAddWorker(directTunnelUtils, txRunner),
146                             tunnelStateInfoNew), ITMConstants.JOB_MAX_RETRIES);
147                 }
148             }
149         }
150     }
151
152     public List<DPNTEPsInfo> getDPNTepListFromDPNId(List<Uint64> dpnIds) {
153         Collection<DPNTEPsInfo> meshedDpnList = this.getAllPresent() ;
154         List<DPNTEPsInfo> cfgDpnList = new ArrayList<>();
155         for (Uint64 dpnId : dpnIds) {
156             for (DPNTEPsInfo teps : meshedDpnList) {
157                 if (dpnId.equals(teps.getDPNID())) {
158                     cfgDpnList.add(teps);
159                 }
160             }
161         }
162         return cfgDpnList;
163     }
164
165     public Optional<DPNTEPsInfo> getDPNTepFromDPNId(Uint64 dpnId) {
166         Collection<DPNTEPsInfo> meshedDpnList = this.getAllPresent() ;
167         return meshedDpnList.stream().filter(info -> dpnId.equals(info.getDPNID())).findFirst();
168     }
169 }