Merge "L2GW: Handling during delete and add of ITM:transport-zone."
[netvirt.git] / vpnservice / elanmanager / elanmanager-impl / src / main / java / org / opendaylight / netvirt / elan / internal / ElanDpnInterfaceClusteredListener.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.internal;
9
10 import java.util.List;
11 import java.util.concurrent.Callable;
12
13 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
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.l2gw.utils.ElanL2GatewayMulticastUtils;
19 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
20 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
21 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
22 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
26 import org.opendaylight.yangtools.concepts.ListenerRegistration;
27 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import com.google.common.collect.Lists;
32 import com.google.common.util.concurrent.ListenableFuture;
33
34 public class ElanDpnInterfaceClusteredListener
35     extends AsyncClusteredDataChangeListenerBase<DpnInterfaces, ElanDpnInterfaceClusteredListener>
36     implements AutoCloseable {
37     private ElanServiceProvider elanServiceProvider = null;
38     private static volatile ElanDpnInterfaceClusteredListener elanDpnInterfaceClusteredListener = null;
39     private ListenerRegistration<DataChangeListener> listenerRegistration;
40
41     private static final Logger LOG = LoggerFactory.getLogger(ElanDpnInterfaceClusteredListener.class);
42
43
44     public ElanDpnInterfaceClusteredListener(ElanServiceProvider elanServiceProvider) {
45         super(DpnInterfaces.class, ElanDpnInterfaceClusteredListener.class);
46         this.elanServiceProvider = elanServiceProvider;
47         registerListener(elanServiceProvider.getBroker());
48     }
49
50     public static ElanDpnInterfaceClusteredListener getElanDpnInterfaceClusteredListener(
51         ElanServiceProvider elanServiceProvider) {
52         if (elanDpnInterfaceClusteredListener == null) {
53             synchronized (ElanDpnInterfaceClusteredListener.class) {
54                 if (elanDpnInterfaceClusteredListener == null) {
55                     elanDpnInterfaceClusteredListener = new ElanDpnInterfaceClusteredListener(elanServiceProvider);
56                 }
57             }
58         }
59         return elanDpnInterfaceClusteredListener;
60     }
61     private void registerListener(final DataBroker db) {
62         try {
63             listenerRegistration = elanServiceProvider.getBroker().registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
64                 getWildCardPath(), ElanDpnInterfaceClusteredListener.this, AsyncDataBroker.DataChangeScope.BASE);
65         } catch (final Exception e) {
66             LOG.error("DpnInterfaces DataChange listener registration fail!", e);
67         }
68     }
69
70     @Override
71     public InstanceIdentifier<DpnInterfaces> getWildCardPath() {
72         return InstanceIdentifier.builder(ElanDpnInterfaces.class).child(ElanDpnInterfacesList.class)
73             .child(DpnInterfaces.class).build();
74     }
75
76     @Override
77     protected ClusteredDataChangeListener getDataChangeListener() {
78         return ElanDpnInterfaceClusteredListener.this;
79     }
80
81     @Override
82     protected AsyncDataBroker.DataChangeScope getDataChangeScope() {
83         return AsyncDataBroker.DataChangeScope.BASE;
84     }
85
86     void handleUpdate(InstanceIdentifier<DpnInterfaces> id, DpnInterfaces dpnInterfaces) {
87         final String elanName = getElanName(id);
88         if (ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName).isEmpty()) {
89             LOG.debug("dpnInterface updation, no external l2 devices to update for elan {} with Dp Id:", elanName,
90                 dpnInterfaces.getDpId());
91             return;
92         }
93         ElanClusterUtils.runOnlyInLeaderNode(elanName, "updating mcast mac upon tunnel event",
94             new Callable<List<ListenableFuture<Void>>>() {
95                 @Override
96                 public List<ListenableFuture<Void>> call() throws Exception {
97                     return Lists.newArrayList(
98                         ElanL2GatewayMulticastUtils.updateRemoteMcastMacOnElanL2GwDevices(elanName));
99                 }
100             });
101     }
102
103     @Override
104     protected void remove(InstanceIdentifier<DpnInterfaces> identifier, final DpnInterfaces dpnInterfaces) {
105         // this is the last dpn interface on this elan
106         final String elanName = getElanName(identifier);
107         LOG.debug("Received ElanDpnInterface removed for for elan {} with Dp Id ", elanName,
108             dpnInterfaces.getDpId());
109
110         if (ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName).isEmpty()) {
111             LOG.debug("dpnInterface removed, no external l2 devices to update for elan {} with Dp Id:", elanName,
112                 dpnInterfaces.getDpId());
113             return;
114         }
115         ElanClusterUtils.runOnlyInLeaderNode(elanName, "handling ElanDpnInterface removed",
116             new Callable<List<ListenableFuture<Void>>>() {
117                 @Override
118                 public List<ListenableFuture<Void>> call() throws Exception {
119                     // deleting Elan L2Gw Devices UcastLocalMacs From Dpn
120                     ElanL2GatewayUtils.deleteElanL2GwDevicesUcastLocalMacsFromDpn(elanName,
121                         dpnInterfaces.getDpId());
122                     // updating remote mcast mac on l2gw devices
123                     return Lists.newArrayList(
124                         ElanL2GatewayMulticastUtils.updateRemoteMcastMacOnElanL2GwDevices(elanName));
125                 }
126             });
127     }
128
129     @Override
130     protected void update(InstanceIdentifier<DpnInterfaces> identifier, DpnInterfaces original,
131                           final DpnInterfaces dpnInterfaces) {
132         LOG.debug("dpninterfaces update fired new size {}", dpnInterfaces.getInterfaces().size());
133         if (dpnInterfaces.getInterfaces().size() == 0) {
134             LOG.debug("dpninterfaces last dpn interface on this elan {} ", dpnInterfaces.getKey());
135             // this is the last dpn interface on this elan
136             handleUpdate(identifier, dpnInterfaces);
137         }
138     }
139
140     @Override
141     protected void add(InstanceIdentifier<DpnInterfaces> identifier, final DpnInterfaces dpnInterfaces) {
142         if (dpnInterfaces.getInterfaces().size() == 1) {
143             LOG.debug("dpninterfaces first dpn interface on this elan {} {} ", dpnInterfaces.getKey(),
144                 dpnInterfaces.getInterfaces().get(0));
145             // this is the first dpn interface on this elan
146             handleUpdate(identifier, dpnInterfaces);
147         }
148     }
149
150     /**
151      * @param identifier
152      * @return
153      */
154     private String getElanName(InstanceIdentifier<DpnInterfaces> identifier) {
155         return identifier.firstKeyOf(ElanDpnInterfacesList.class).getElanInstanceName();
156     }
157
158 }