3b727c433837264c4b8184efc5404854a07683c7
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / recovery / impl / EosChangeEventHandler.java
1 /*
2  * Copyright (c) 2020 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 package org.opendaylight.genius.itm.recovery.impl;
9
10 import static org.opendaylight.mdsal.binding.util.Datastore.OPERATIONAL;
11
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.List;
15 import java.util.Set;
16 import java.util.concurrent.ConcurrentHashMap;
17 import java.util.concurrent.ConcurrentMap;
18 import java.util.concurrent.ExecutionException;
19 import javax.inject.Inject;
20 import javax.inject.Singleton;
21 import org.opendaylight.genius.itm.cache.TunnelStateCache;
22 import org.opendaylight.genius.itm.impl.ItmUtils;
23 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
24 import org.opendaylight.mdsal.binding.api.DataBroker;
25 import org.opendaylight.mdsal.binding.api.ReadTransaction;
26 import org.opendaylight.mdsal.binding.util.Datastore.Operational;
27 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
28 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
29 import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
30 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 @Singleton
47 public class EosChangeEventHandler {
48
49     private static final Logger LOG = LoggerFactory.getLogger(EosChangeEventHandler.class);
50     private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
51
52     private final DataBroker dataBroker;
53     private final TunnelStateCache tunnelStateCache;
54     private final ManagedNewTransactionRunner txRunner;
55     private final DirectTunnelUtils directTunnelUtils;
56
57     @Inject
58     public EosChangeEventHandler(DataBroker dataBroker, TunnelStateCache tunnelStateCache,
59                                  DirectTunnelUtils directTunnelUtils) {
60         LOG.info("registering EOS change handlers");
61         this.tunnelStateCache = tunnelStateCache;
62         this.dataBroker = dataBroker;
63         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
64         this.directTunnelUtils = directTunnelUtils;
65     }
66
67     public void recoverUnknownTunnelsOnEosSwitch() {
68         LOG.debug("EosChangeListener: recovering unknown tunnels");
69
70         if (!directTunnelUtils.isEntityOwner()) {
71             LOG.debug("Not an entity owner, returning...");
72             return;
73         }
74         List<StateTunnelList> unknownTunnels = getUnknownTunnelsFromDefaultOper();
75         if (unknownTunnels.isEmpty()) {
76             LOG.debug("Empty oper DS or No unknown tunnels in ITM oper DS");
77         } else {
78             ConcurrentMap<String, String> tunnelNameToNodeConnectorIdValue = prepareKeyForInventoryOper(unknownTunnels);
79             Set<ConcurrentMap.Entry<String,String>> entrySet = tunnelNameToNodeConnectorIdValue.entrySet();
80             ReadTransaction readOnlyTx = dataBroker.newReadOnlyTransaction();
81             for (ConcurrentMap.Entry<String,String> entry : entrySet) {
82                 String tunnelName = entry.getKey();
83                 String nodeConnectorIdValue = entry.getValue();
84                 String nodeIdValue = nodeConnectorIdValue.substring(0, nodeConnectorIdValue.lastIndexOf(":"));
85                 NodeConnectorId nodeConnectorId = new NodeConnectorId(nodeConnectorIdValue);
86                 NodeId nodeId = new NodeId(nodeIdValue);
87                 InstanceIdentifier<NodeConnector> ncIdentifier = InstanceIdentifier.builder(Nodes.class)
88                         .child(Node.class, new NodeKey(nodeId))
89                         .child(NodeConnector.class, new NodeConnectorKey(nodeConnectorId)).build();
90
91                 try {
92                     if (readOnlyTx.exists(LogicalDatastoreType.OPERATIONAL, ncIdentifier).get()) {
93                         txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
94                             updateTunnelState(tunnelName, tx);
95                         });
96                     }
97                 } catch (InterruptedException e) {
98                     LOG.error("EosChangeListener: Inventory oper read failed for {}, Reason: {}",
99                             ncIdentifier, e.getMessage());
100                 } catch (ExecutionException e) {
101                     LOG.error("EosChangeListener: Inventory oper read failed for {}, Reason: {}",
102                             ncIdentifier, e.getMessage());
103                 }
104             }
105         }
106     }
107
108
109     ////////private method area////////
110     private List<StateTunnelList> getUnknownTunnelsFromDefaultOper() {
111         List<StateTunnelList> unknownTunnels = new ArrayList<>();
112         Collection<StateTunnelList> tunnelList = tunnelStateCache.getAllPresent();
113         if (!tunnelList.isEmpty()) {
114             for (StateTunnelList stateTunnelEntry : tunnelList) {
115                 if (stateTunnelEntry.getOperState().equals(TunnelOperStatus.Unknown)) {
116                     unknownTunnels.add(stateTunnelEntry);
117                 }
118             }
119         } else {
120             LOG.debug("ITM oper DS is empty.");
121             EVENT_LOGGER.debug("ITM-EosChange, oper DS is empty.");
122         }
123         return unknownTunnels;
124     }
125
126     private ConcurrentMap<String, String> prepareKeyForInventoryOper(List<StateTunnelList> unknownTunnels) {
127         ConcurrentMap<String, String> tunnelNameToNodeConnectorIdValue = new ConcurrentHashMap<>();
128         for (StateTunnelList unknownTunnel:unknownTunnels) {
129             tunnelNameToNodeConnectorIdValue.put(unknownTunnel.getTunnelInterfaceName(),
130                     "openflow:" + unknownTunnel.getSrcInfo().getTepDeviceId() + ":" + unknownTunnel.getPortNumber());
131         }
132         return tunnelNameToNodeConnectorIdValue;
133     }
134
135     private void updateTunnelState(String interfaceName, TypedWriteTransaction<Operational> writeOnlyTx) {
136         StateTunnelListBuilder stateTnlBuilder = new StateTunnelListBuilder();
137         stateTnlBuilder.withKey(new StateTunnelListKey(interfaceName));
138         stateTnlBuilder.setTunnelState(true);
139         stateTnlBuilder.setOperState(TunnelOperStatus.Up);
140         InstanceIdentifier<StateTunnelList> tnlStateId = ItmUtils.buildStateTunnelListId(
141                 new StateTunnelListKey(interfaceName));
142         writeOnlyTx.merge(tnlStateId, stateTnlBuilder.build());
143     }
144 }