Bug 5129 : Added more locks to avoid concurrent DS modification conflicts
[vpnservice.git] / interfacemgr / interfacemgr-impl / src / main / java / org / opendaylight / vpnservice / interfacemgr / listeners / VlanMemberConfigListener.java
1 /*
2  * Copyright (c) 2015 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.interfacemgr.listeners;
9
10 import com.google.common.util.concurrent.ListenableFuture;
11 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
12 import org.opendaylight.idmanager.IdManager;
13 import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
14 import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
15 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsVlanMemberConfigAddHelper;
16 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsVlanMemberConfigRemoveHelper;
17 import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsVlanMemberConfigUpdateHelper;
18 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
25 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 import java.util.List;
30 import java.util.concurrent.Callable;
31
32 public class VlanMemberConfigListener extends AsyncDataTreeChangeListenerBase<Interface, VlanMemberConfigListener> {
33     private static final Logger LOG = LoggerFactory.getLogger(VlanMemberConfigListener.class);
34     private DataBroker dataBroker;
35     private IdManagerService idManager;
36     private AlivenessMonitorService alivenessMonitorService;
37     private IMdsalApiManager mdsalApiManager;
38
39     public VlanMemberConfigListener(final DataBroker dataBroker, final IdManagerService idManager,
40                                     final AlivenessMonitorService alivenessMonitorService,
41                                     final IMdsalApiManager mdsalApiManager) {
42         super(Interface.class, VlanMemberConfigListener.class);
43         this.dataBroker = dataBroker;
44         this.idManager = idManager;
45         this.alivenessMonitorService = alivenessMonitorService;
46         this.mdsalApiManager = mdsalApiManager;
47     }
48
49     @Override
50     protected InstanceIdentifier<Interface> getWildCardPath() {
51         return InstanceIdentifier.create(Interfaces.class).child(Interface.class);
52     }
53
54     @Override
55     protected void remove(InstanceIdentifier<Interface> key, Interface interfaceOld) {
56         IfL2vlan ifL2vlan = interfaceOld.getAugmentation(IfL2vlan.class);
57         if (ifL2vlan == null) {
58             return;
59         }
60
61         if (ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.TrunkMember) {
62             return;
63         }
64
65         ParentRefs parentRefs = interfaceOld.getAugmentation(ParentRefs.class);
66         if (parentRefs == null) {
67             LOG.error("Attempt to remove Vlan Trunk-Member {} without a parent interface", interfaceOld);
68             return;
69         }
70
71         String lowerLayerIf = parentRefs.getParentInterface();
72         if (lowerLayerIf.equals(interfaceOld.getName())) {
73             LOG.error("Attempt to remove Vlan Trunk-Member {} with same parent interface name.", interfaceOld);
74             return;
75         }
76
77         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
78         RendererConfigRemoveWorker removeWorker = new RendererConfigRemoveWorker(key, interfaceOld, parentRefs, ifL2vlan);
79         coordinator.enqueueJob(lowerLayerIf, removeWorker);
80     }
81
82     @Override
83     protected void update(InstanceIdentifier<Interface> key, Interface interfaceOld, Interface interfaceNew) {
84         IfL2vlan ifL2vlanNew = interfaceNew.getAugmentation(IfL2vlan.class);
85         if (ifL2vlanNew == null) {
86             return;
87         }
88         if (ifL2vlanNew.getL2vlanMode() != IfL2vlan.L2vlanMode.TrunkMember) {
89             LOG.error("Configuration Error. Attempt to modify Vlan Mode of interface: {} " +
90                     "to interface: {}", interfaceOld, interfaceNew);
91             return;
92         }
93
94         ParentRefs parentRefsNew = interfaceNew.getAugmentation(ParentRefs.class);
95         if (parentRefsNew == null) {
96             LOG.error("Configuration Error. Attempt to update Vlan Trunk-Member {} without a " +
97                     "parent interface", interfaceNew);
98             return;
99         }
100
101         String lowerLayerIf = parentRefsNew.getParentInterface();
102         if (lowerLayerIf.equals(interfaceNew.getName())) {
103             LOG.error("Configuration Error. Attempt to update Vlan Trunk-Member {} with same parent " +
104                     "interface name.", interfaceNew);
105             return;
106         }
107
108         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
109         RendererConfigUpdateWorker updateWorker = new RendererConfigUpdateWorker(key, interfaceNew, interfaceOld,
110                 parentRefsNew, ifL2vlanNew);
111         coordinator.enqueueJob(lowerLayerIf, updateWorker);
112     }
113
114     @Override
115     protected void add(InstanceIdentifier<Interface> key, Interface interfaceNew) {
116         IfL2vlan ifL2vlan = interfaceNew.getAugmentation(IfL2vlan.class);
117         if (ifL2vlan == null) {
118             return;
119         }
120
121         if (ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.TrunkMember) {
122             return;
123         }
124
125         ParentRefs parentRefs = interfaceNew.getAugmentation(ParentRefs.class);
126         if (parentRefs == null) {
127             LOG.error("Attempt to add Vlan Trunk-Member {} without a parent interface", interfaceNew);
128             return;
129         }
130
131         String lowerLayerIf = parentRefs.getParentInterface();
132         if (lowerLayerIf.equals(interfaceNew.getName())) {
133             LOG.error("Attempt to add Vlan Trunk-Member {} with same parent interface name.", interfaceNew);
134             return;
135         }
136
137         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
138         RendererConfigAddWorker configWorker = new RendererConfigAddWorker(key, interfaceNew, parentRefs, ifL2vlan);
139         coordinator.enqueueJob(lowerLayerIf, configWorker);
140     }
141
142     @Override
143     protected VlanMemberConfigListener getDataTreeChangeListener() {
144         return VlanMemberConfigListener.this;
145     }
146
147     private class RendererConfigAddWorker implements Callable<List<ListenableFuture<Void>>> {
148         InstanceIdentifier<Interface> key;
149         Interface interfaceNew;
150         IfL2vlan ifL2vlan;
151         ParentRefs parentRefs;
152
153         public RendererConfigAddWorker(InstanceIdentifier<Interface> key, Interface interfaceNew,
154                                        ParentRefs parentRefs, IfL2vlan ifL2vlan) {
155             this.key = key;
156             this.interfaceNew = interfaceNew;
157             this.ifL2vlan = ifL2vlan;
158             this.parentRefs = parentRefs;
159         }
160
161         @Override
162         public List<ListenableFuture<Void>> call() throws Exception {
163             // If another renderer(for eg : CSS) needs to be supported, check can be performed here
164             // to call the respective helpers.
165             return OvsVlanMemberConfigAddHelper.addConfiguration(dataBroker, parentRefs, interfaceNew,
166                     ifL2vlan, idManager);
167         }
168     }
169
170     private class RendererConfigUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
171         InstanceIdentifier<Interface> key;
172         Interface interfaceNew;
173         Interface interfaceOld;
174         IfL2vlan ifL2vlanNew;
175         ParentRefs parentRefsNew;
176
177         public RendererConfigUpdateWorker(InstanceIdentifier<Interface> key, Interface interfaceNew,
178                                        Interface interfaceOld, ParentRefs parentRefsNew, IfL2vlan ifL2vlanNew) {
179             this.key = key;
180             this.interfaceNew = interfaceNew;
181             this.interfaceOld = interfaceOld;
182             this.ifL2vlanNew = ifL2vlanNew;
183             this.parentRefsNew = parentRefsNew;
184         }
185
186         @Override
187         public List<ListenableFuture<Void>> call() throws Exception {
188             // If another renderer(for eg : CSS) needs to be supported, check can be performed here
189             // to call the respective helpers.
190             return OvsVlanMemberConfigUpdateHelper.updateConfiguration(dataBroker, alivenessMonitorService,
191                     parentRefsNew, interfaceOld, ifL2vlanNew, interfaceNew, idManager, mdsalApiManager);
192         }
193     }
194
195     private class RendererConfigRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
196         InstanceIdentifier<Interface> key;
197         Interface interfaceOld;
198         IfL2vlan ifL2vlan;
199         ParentRefs parentRefs;
200
201         public RendererConfigRemoveWorker(InstanceIdentifier<Interface> key, Interface interfaceOld,
202                                           ParentRefs parentRefs, IfL2vlan ifL2vlan) {
203             this.key = key;
204             this.interfaceOld = interfaceOld;
205             this.ifL2vlan = ifL2vlan;
206             this.parentRefs = parentRefs;
207         }
208
209         @Override
210         public List<ListenableFuture<Void>> call() throws Exception {
211             // If another renderer(for eg : CSS) needs to be supported, check can be performed here
212             // to call the respective helpers.
213             return OvsVlanMemberConfigRemoveHelper.removeConfiguration(dataBroker, parentRefs, interfaceOld,
214                     ifL2vlan, idManager);
215         }
216     }
217 }