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