Merge "Enable NetVirt Maven site"
[netvirt.git] / vpnservice / elanmanager / elanmanager-impl / src / main / java / org / opendaylight / netvirt / elan / l2gw / listeners / HwvtepRemoteMcastMacListener.java
1 /*
2  * Copyright (c) 2016 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.listeners;
9
10 import java.util.List;
11 import java.util.concurrent.Callable;
12 import java.util.concurrent.atomic.AtomicBoolean;
13
14 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.netvirt.elan.utils.ElanUtils;
19 import org.opendaylight.netvirt.elan.utils.ElanConstants;
20 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
21 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
22 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
23 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
24 import org.opendaylight.genius.utils.SystemPropertyReader;
25 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 import com.google.common.base.Optional;
35 import com.google.common.util.concurrent.ListenableFuture;
36
37 /**
38  * The listener class for listening to {@code RemoteMcastMacs}
39  * add/delete/update.
40  *
41  * @see RemoteMcastMacs
42  */
43 public class HwvtepRemoteMcastMacListener
44         extends AsyncClusteredDataChangeListenerBase<RemoteMcastMacs, HwvtepRemoteMcastMacListener> {
45
46     /** The Constant LOG. */
47     private static final Logger LOG = LoggerFactory.getLogger(HwvtepRemoteMcastMacListener.class);
48
49     /** The node id. */
50     private NodeId nodeId;
51
52     private List<IpAddress> expectedPhyLocatorIps;
53
54     DataBroker broker;
55
56     String logicalSwitchName;
57
58     AtomicBoolean executeTask = new AtomicBoolean(true);
59
60     Callable<List<ListenableFuture<Void>>> taskToRun;
61
62     static DataStoreJobCoordinator dataStoreJobCoordinator;
63
64     public static void setDataStoreJobCoordinator(DataStoreJobCoordinator ds) {
65         dataStoreJobCoordinator = ds;
66     }
67
68     /**
69      * Instantiates a new remote mcast mac listener.
70      *
71      * @param broker
72      *            the mdsal databroker reference
73      * @param logicalSwitchName
74      *            the logical switch name
75      * @param l2GatewayDevice
76      *            the l2 gateway device
77      * @param expectedPhyLocatorIps
78      *            the expected phy locator ips
79      * @param task
80      *            the task to be run upon data presence
81      * @throws Exception
82      *             the exception
83      */
84     public HwvtepRemoteMcastMacListener(DataBroker broker, String logicalSwitchName, L2GatewayDevice l2GatewayDevice,
85             List<IpAddress> expectedPhyLocatorIps, Callable<List<ListenableFuture<Void>>> task) throws Exception {
86         super(RemoteMcastMacs.class, HwvtepRemoteMcastMacListener.class);
87         this.nodeId = new NodeId(l2GatewayDevice.getHwvtepNodeId());
88         this.broker = broker;
89         this.taskToRun = task;
90         this.logicalSwitchName = logicalSwitchName;
91         this.expectedPhyLocatorIps = expectedPhyLocatorIps;
92         LOG.info("registering the listener for mcast mac ");
93         registerListener(LogicalDatastoreType.OPERATIONAL, broker);
94         LOG.info("registered the listener for mcast mac ");
95         if (isDataPresentInOpDs(getWildCardPath())) {
96             LOG.info("mcast mac already present running the task ");
97             if (executeTask.compareAndSet(true, false)) {
98                 runTask();
99             }
100         }
101     }
102
103     private boolean isDataPresentInOpDs(InstanceIdentifier<RemoteMcastMacs> path) throws Exception {
104         Optional<RemoteMcastMacs> mac = null;
105         try {
106             mac = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, path);
107         } catch (Throwable e) {
108         }
109         if (mac == null || !mac.isPresent()) {
110             return false;
111         }
112         if (this.expectedPhyLocatorIps != null && !this.expectedPhyLocatorIps.isEmpty()) {
113             RemoteMcastMacs remoteMcastMac = mac.get();
114             if (remoteMcastMac.getLocatorSet() == null || remoteMcastMac.getLocatorSet().isEmpty()) {
115                 return false;
116             }
117             for (IpAddress ip : this.expectedPhyLocatorIps) {
118                 boolean ipExists = ElanL2GatewayUtils.checkIfPhyLocatorAlreadyExistsInRemoteMcastEntry(this.nodeId,
119                         remoteMcastMac, ip);
120                 if (!ipExists) {
121                     LOG.trace("IP [{}] not found in RemoteMcastMacs for node [{}]", String.valueOf(ip.getValue()),
122                             this.nodeId.getValue());
123                     return false;
124                 }
125             }
126         }
127         return true;
128     }
129
130     /*
131      * (non-Javadoc)
132      *
133      * @see
134      * org.opendaylight.genius.datastoreutils.AsyncDataChangeListenerBase#
135      * getWildCardPath()
136      */
137     @Override
138     public InstanceIdentifier<RemoteMcastMacs> getWildCardPath() {
139         return HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId,
140                 logicalSwitchName, new MacAddress(ElanConstants.UNKNOWN_DMAC));
141     }
142
143     /*
144      * (non-Javadoc)
145      *
146      * @see
147      * org.opendaylight.genius.datastoreutils.AsyncDataChangeListenerBase#
148      * getDataChangeListener()
149      */
150     @Override
151     protected ClusteredDataChangeListener getDataChangeListener() {
152         return HwvtepRemoteMcastMacListener.this;
153     }
154
155     /*
156      * (non-Javadoc)
157      *
158      * @see
159      * org.opendaylight.genius.datastoreutils.AsyncDataChangeListenerBase#
160      * getDataChangeScope()
161      */
162     @Override
163     protected AsyncDataBroker.DataChangeScope getDataChangeScope() {
164         return AsyncDataBroker.DataChangeScope.BASE;
165     }
166
167     /*
168      * (non-Javadoc)
169      *
170      * @see
171      * org.opendaylight.genius.datastoreutils.AsyncDataChangeListenerBase#
172      * remove(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
173      * org.opendaylight.yangtools.yang.binding.DataObject)
174      */
175     @Override
176     protected void remove(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs deleted) {
177         LOG.trace("Received Remove DataChange Notification for identifier: {}, RemoteMcastMacs: {}", identifier,
178                 deleted);
179     }
180
181     /*
182      * (non-Javadoc)
183      *
184      * @see
185      * org.opendaylight.genius.datastoreutils.AsyncDataChangeListenerBase#
186      * update(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
187      * org.opendaylight.yangtools.yang.binding.DataObject,
188      * org.opendaylight.yangtools.yang.binding.DataObject)
189      */
190     @Override
191     protected void update(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs old,
192             RemoteMcastMacs newdata) {
193         LOG.trace("Received Update DataChange Notification for identifier: {}, RemoteMcastMacs old: {}, new: {}."
194                 + "No Action Performed.", identifier, old, newdata);
195     }
196
197     /*
198      * (non-Javadoc)
199      *
200      * @see
201      * org.opendaylight.genius.datastoreutils.AsyncDataChangeListenerBase#
202      * add(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
203      * org.opendaylight.yangtools.yang.binding.DataObject)
204      */
205     @Override
206     protected void add(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs mcastMac) {
207         LOG.debug("Received Add DataChange Notification for identifier: {}, RemoteMcastMacs: {}", identifier, mcastMac);
208         // No isDataPresentInOpDs check is done as assuming all the expected phy
209         // locator ips will be available during add
210         if (executeTask.compareAndSet(true, false)) {
211             runTask();
212         }
213     }
214
215     void runTask() {
216         try {
217
218             String jobKey = ElanL2GatewayUtils.getL2GatewayConnectionJobKey(nodeId.getValue(), nodeId.getValue());
219             dataStoreJobCoordinator.enqueueJob(jobKey, taskToRun, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
220         } catch (Exception e) {
221             LOG.error("Failed to handle remote mcast mac - add: {}", e);
222         } finally {
223             try {
224                 close();
225             } catch (Exception e) {
226                 LOG.warn("Failed to close McastMacSwitchListener: {}", e);
227             }
228         }
229     }
230 }