NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / 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 com.google.common.util.concurrent.ListenableFuture;
11 import java.util.List;
12 import java.util.Optional;
13 import java.util.concurrent.Callable;
14 import java.util.concurrent.atomic.AtomicBoolean;
15 import org.opendaylight.genius.datastoreutils.hwvtep.HwvtepClusteredDataTreeChangeListener;
16 import org.opendaylight.genius.utils.SystemPropertyReader;
17 import org.opendaylight.genius.utils.hwvtep.HwvtepNodeHACache;
18 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
19 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
20 import org.opendaylight.infrautils.utils.concurrent.Executors;
21 import org.opendaylight.mdsal.binding.api.DataBroker;
22 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
23 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
24 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
25 import org.opendaylight.netvirt.elan.utils.ElanConstants;
26 import org.opendaylight.netvirt.elan.utils.ElanUtils;
27 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * The listener class for listening to {@code RemoteMcastMacs}
38  * add/delete/update.
39  *
40  * @see RemoteMcastMacs
41  */
42 public class HwvtepRemoteMcastMacListener
43         extends HwvtepClusteredDataTreeChangeListener<RemoteMcastMacs, HwvtepRemoteMcastMacListener> {
44
45     /** The Constant LOG. */
46     private static final Logger LOG = LoggerFactory.getLogger(HwvtepRemoteMcastMacListener.class);
47
48     /** The node id. */
49     private final NodeId nodeId;
50
51     private final List<IpAddress> expectedPhyLocatorIps;
52
53     private final ElanUtils elanUtils;
54
55     String logicalSwitchName;
56
57     AtomicBoolean executeTask = new AtomicBoolean(true);
58
59     Callable<List<? extends ListenableFuture<?>>> taskToRun;
60
61     private final JobCoordinator jobCoordinator;
62
63     /**
64      * Instantiates a new remote mcast mac listener.
65      * @param broker DataBroker
66      * @param elanUtils ElanUtils
67      * @param logicalSwitchName LS name of the network
68      * @param l2GatewayDevice L2GatewayDevice
69      * @param expectedPhyLocatorIps List of IP addresses
70      * @param task List of tasks to be executed on callbacks
71      * @param jobCoordinator JobCoordinator
72      * @throws Exception throws Exception
73      */
74     public HwvtepRemoteMcastMacListener(DataBroker broker, ElanUtils elanUtils, String logicalSwitchName,
75                                         L2GatewayDevice l2GatewayDevice,
76                                         List<IpAddress> expectedPhyLocatorIps,
77                                         Callable<List<? extends ListenableFuture<?>>> task,
78                                         JobCoordinator jobCoordinator, HwvtepNodeHACache hwvtepNodeHACache)
79                                                 throws Exception {
80         super(broker, DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL,
81             HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(new NodeId(l2GatewayDevice.getHwvtepNodeId()),
82             logicalSwitchName, new MacAddress(ElanConstants.UNKNOWN_DMAC))),
83             Executors.newListeningSingleThreadExecutor("HwvtepRemoteMcastMacListener", LOG),
84             hwvtepNodeHACache);
85         this.elanUtils = elanUtils;
86         this.nodeId = new NodeId(l2GatewayDevice.getHwvtepNodeId());
87         this.taskToRun = task;
88         this.logicalSwitchName = logicalSwitchName;
89         this.expectedPhyLocatorIps = expectedPhyLocatorIps;
90         this.jobCoordinator = jobCoordinator;
91         LOG.info("registering the listener for mcast mac ");
92         //registerListener(LogicalDatastoreType.OPERATIONAL, broker);
93         LOG.info("registered the listener for mcast mac");
94         if (isDataPresentInOpDs(getWildCardPath())) {
95             LOG.info("mcast mac already present running the task ");
96             if (executeTask.compareAndSet(true, false)) {
97                 runTask();
98             }
99         }
100     }
101
102     private boolean isDataPresentInOpDs(InstanceIdentifier<RemoteMcastMacs> path) throws Exception {
103         Optional<RemoteMcastMacs> mac = elanUtils.read2(LogicalDatastoreType.OPERATIONAL, path);
104         if (!mac.isPresent()) {
105             return false;
106         }
107         if (this.expectedPhyLocatorIps != null && !this.expectedPhyLocatorIps.isEmpty()) {
108             RemoteMcastMacs remoteMcastMac = mac.get();
109             if (remoteMcastMac.getLocatorSet() == null || remoteMcastMac.getLocatorSet().isEmpty()) {
110                 return false;
111             }
112             for (IpAddress ip : this.expectedPhyLocatorIps) {
113                 boolean ipExists = ElanL2GatewayUtils.checkIfPhyLocatorAlreadyExistsInRemoteMcastEntry(this.nodeId,
114                         remoteMcastMac, ip);
115                 if (!ipExists) {
116                     LOG.trace("IP [{}] not found in RemoteMcastMacs for node [{}]", ip.stringValue(),
117                             this.nodeId.getValue());
118                     return false;
119                 }
120             }
121         }
122         return true;
123     }
124
125     public InstanceIdentifier<RemoteMcastMacs> getWildCardPath() {
126         return HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId,
127                 logicalSwitchName, new MacAddress(ElanConstants.UNKNOWN_DMAC));
128     }
129
130     @Override
131     protected void removed(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs deleted) {
132         LOG.trace("Received Remove DataChange Notification for identifier: {}, RemoteMcastMacs: {}", identifier,
133                 deleted);
134     }
135
136     @Override
137     protected void updated(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs old,
138             RemoteMcastMacs newdata) {
139         LOG.trace("Received Update DataChange Notification for identifier: {}, RemoteMcastMacs old: {}, new: {}."
140                 + "No Action Performed.", identifier, old, newdata);
141     }
142
143     @Override
144     protected void added(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs mcastMac) {
145         LOG.debug("Received Add DataChange Notification for identifier: {}, RemoteMcastMacs: {}", identifier, mcastMac);
146         // No isDataPresentInOpDs check is done as assuming all the expected phy
147         // locator ips will be available during add
148         if (executeTask.compareAndSet(true, false)) {
149             runTask();
150         }
151     }
152
153     @SuppressWarnings("checkstyle:IllegalCatch") // TODO remove when using AutoCloseables
154     void runTask() {
155         try {
156             String jobKey = ElanL2GatewayUtils.getL2GatewayConnectionJobKey(nodeId.getValue());
157             jobCoordinator.enqueueJob(jobKey, taskToRun,
158                     SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
159         } finally {
160             // TODO https://git.opendaylight.org/gerrit/#/c/44145/
161             // AutoCloseables.closeAndLog(this);
162             try {
163                 close();
164             } catch (Exception e) {
165                 LOG.warn("Failed to close McastMacSwitchListener", e);
166             }
167         }
168     }
169 }