2 * Copyright (c) 2020 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.genius.itm.recovery.impl;
10 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.List;
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.infra.Datastore.Operational;
22 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
23 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
24 import org.opendaylight.genius.infra.TypedWriteTransaction;
25 import org.opendaylight.genius.itm.cache.TunnelStateCache;
26 import org.opendaylight.genius.itm.impl.ItmUtils;
27 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
28 import org.opendaylight.mdsal.binding.api.DataBroker;
29 import org.opendaylight.mdsal.binding.api.ReadTransaction;
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;
47 public class EosChangeEventHandler {
49 private static final Logger LOG = LoggerFactory.getLogger(EosChangeEventHandler.class);
50 private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
52 private final DataBroker dataBroker;
53 private final TunnelStateCache tunnelStateCache;
54 private final ManagedNewTransactionRunner txRunner;
55 private final DirectTunnelUtils directTunnelUtils;
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;
67 public void recoverUnknownTunnelsOnEosSwitch() {
68 LOG.debug("EosChangeListener: recovering unknown tunnels");
70 if (!directTunnelUtils.isEntityOwner()) {
71 LOG.debug("Not an entity owner, returning...");
74 List<StateTunnelList> unknownTunnels = getUnknownTunnelsFromDefaultOper();
75 if (unknownTunnels.isEmpty()) {
76 LOG.debug("Empty oper DS or No unknown tunnels in ITM oper DS");
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();
92 if (readOnlyTx.exists(LogicalDatastoreType.OPERATIONAL, ncIdentifier).get()) {
93 txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
94 updateTunnelState(tunnelName, tx);
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());
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);
120 LOG.debug("ITM oper DS is empty.");
121 EVENT_LOGGER.debug("ITM-EosChange, oper DS is empty.");
123 return unknownTunnels;
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());
132 return tunnelNameToNodeConnectorIdValue;
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());