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