b7b4761be6be018b15f453bb2ffea428c1640a2b
[netvirt.git] / vpnservice / elanmanager / elanmanager-impl / src / main / java / org / opendaylight / netvirt / elan / l2gw / ha / listeners / HwvtepNodeBaseListener.java
1 /*
2  * Copyright © 2016, 2017 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.netvirt.elan.l2gw.ha.listeners;
9
10 import java.util.Collection;
11 import java.util.HashMap;
12 import java.util.Map;
13 import java.util.concurrent.ExecutionException;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
16 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
17 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
18 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
19 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
22 import org.opendaylight.genius.datastoreutils.TaskRetryLooper;
23 import org.opendaylight.genius.utils.hwvtep.HwvtepHACache;
24 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
25 import org.opendaylight.netvirt.elan.l2gw.ha.HwvtepHAUtil;
26 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
27 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
28 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
30 import org.opendaylight.yangtools.concepts.ListenerRegistration;
31 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 public abstract class HwvtepNodeBaseListener implements DataTreeChangeListener<Node>, AutoCloseable {
36
37     public static final Logger LOG = LoggerFactory.getLogger(HwvtepNodeBaseListener.class);
38     private static final int STARTUP_LOOP_TICK = 500;
39     private static final int STARTUP_LOOP_MAX_RETRIES = 8;
40
41     static HwvtepHACache hwvtepHACache = HwvtepHACache.getInstance();
42
43     private ListenerRegistration<HwvtepNodeBaseListener> registration;
44     DataBroker db;
45
46     public HwvtepNodeBaseListener(LogicalDatastoreType datastoreType, DataBroker dataBroker) throws Exception {
47         db = dataBroker;
48         registerListener(datastoreType, db);
49     }
50
51     public void registerListener(LogicalDatastoreType dsType, final DataBroker db) throws Exception {
52         final DataTreeIdentifier<Node> treeId = new DataTreeIdentifier<>(dsType, getWildcardPath());
53         TaskRetryLooper looper = new TaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
54         registration = looper.loopUntilNoException(() ->
55                 db.registerDataTreeChangeListener(treeId, HwvtepNodeBaseListener.this));
56     }
57
58     @Override
59     public void onDataTreeChanged(final Collection<DataTreeModification<Node>> changes) {
60         HAJobScheduler.getInstance().submitJob(() -> {
61             ReadWriteTransaction tx = getTx();
62             try {
63                 processConnectedNodes(changes, tx);
64                 processUpdatedNodes(changes, tx);
65                 processDisconnectedNodes(changes, tx);
66                 tx.submit().get();
67             } catch (InterruptedException e1) {
68                 LOG.error("InterruptedException " + e1.getMessage());
69             } catch (ExecutionException e2) {
70                 LOG.error("ExecutionException" + e2.getMessage());
71             } catch (ReadFailedException e3) {
72                 LOG.error("ReadFailedException" + e3.getMessage());
73             }
74         });
75     }
76
77     private void processUpdatedNodes(Collection<DataTreeModification<Node>> changes,
78                                      ReadWriteTransaction tx)
79             throws ReadFailedException, ExecutionException, InterruptedException {
80         for (DataTreeModification<Node> change : changes) {
81             final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
82             final DataObjectModification<Node> mod = change.getRootNode();
83             String nodeId = key.firstKeyOf(Node.class).getNodeId().getValue();
84             Node updated = HwvtepHAUtil.getUpdated(mod);
85             Node original = HwvtepHAUtil.getOriginal(mod);
86             if (updated != null && original != null) {
87                 if (updated != null && original != null) {
88                     if (!nodeId.contains(HwvtepHAUtil.PHYSICALSWITCH)) {
89                         onGlobalNodeUpdate(key, updated, original, tx);
90                     } else {
91                         onPsNodeUpdate(key, updated, original, tx);
92                     }
93                 }
94             }
95         }
96     }
97
98     private void processDisconnectedNodes(Collection<DataTreeModification<Node>> changes,
99                                           ReadWriteTransaction tx)
100             throws InterruptedException, ExecutionException, ReadFailedException {
101
102         for (DataTreeModification<Node> change : changes) {
103             final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
104             final DataObjectModification<Node> mod = change.getRootNode();
105             Node deleted = HwvtepHAUtil.getRemoved(mod);
106             String nodeId = key.firstKeyOf(Node.class).getNodeId().getValue();
107             if (deleted != null) {
108                 if (!nodeId.contains(HwvtepHAUtil.PHYSICALSWITCH)) {
109                     LOG.info("Handle global node delete {}", deleted.getNodeId().getValue());
110                     onGlobalNodeDelete(key, deleted, tx);
111                 } else {
112                     LOG.error("Handle ps node node delete {}", deleted.getNodeId().getValue());
113                     onPsNodeDelete(key, deleted, tx);
114                 }
115             }
116         }
117     }
118
119     void processConnectedNodes(Collection<DataTreeModification<Node>> changes,
120                                ReadWriteTransaction tx)
121             throws ReadFailedException, ExecutionException,
122         InterruptedException {
123         Map<String, Boolean> processedNodes = new HashMap<>();
124         for (DataTreeModification<Node> change : changes) {
125             InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
126             DataObjectModification<Node> mod = change.getRootNode();
127             Node node = HwvtepHAUtil.getCreated(mod);
128             String nodeId = key.firstKeyOf(Node.class).getNodeId().getValue();
129             if (node != null) {
130                 if (!nodeId.contains(HwvtepHAUtil.PHYSICALSWITCH)) {
131                     LOG.info("Handle global node add {}", node.getNodeId().getValue());
132                     onGlobalNodeAdd(key, node, tx);
133                 } else {
134                     LOG.error("Handle ps node add {}", node.getNodeId().getValue());
135                     onPsNodeAdd(key, node, tx);
136                 }
137             }
138         }
139     }
140
141     private InstanceIdentifier<Node> getWildcardPath() {
142         InstanceIdentifier<Node> path = InstanceIdentifier
143                 .create(NetworkTopology.class)
144                 .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID))
145                 .child(Node.class);
146         return path;
147     }
148
149     @Override
150     public void close() throws Exception {
151         if (registration != null) {
152             registration.close();
153         }
154     }
155
156     ReadWriteTransaction getTx() {
157         return db.newReadWriteTransaction();
158     }
159
160     //default methods
161     void onGlobalNodeDelete(InstanceIdentifier<Node> key, Node added, ReadWriteTransaction tx)
162             throws InterruptedException, ExecutionException, ReadFailedException {
163     }
164
165     void onPsNodeDelete(InstanceIdentifier<Node> key, Node addedPSNode, ReadWriteTransaction tx)
166             throws ReadFailedException {
167
168     }
169
170     void onGlobalNodeAdd(InstanceIdentifier<Node> key, Node added, ReadWriteTransaction tx) {
171
172     }
173
174     void onPsNodeAdd(InstanceIdentifier<Node> key, Node addedPSNode, ReadWriteTransaction tx)
175             throws ReadFailedException, InterruptedException, ExecutionException {
176
177     }
178
179     void onGlobalNodeUpdate(InstanceIdentifier<Node> key, Node updated, Node original, ReadWriteTransaction tx)
180             throws ReadFailedException, InterruptedException, ExecutionException {
181
182     }
183
184     void onPsNodeUpdate(InstanceIdentifier<Node> key, Node updated, Node original, ReadWriteTransaction tx)
185             throws ReadFailedException, InterruptedException, ExecutionException {
186
187     }
188
189 }