1d9067655f7598956aeab49b1fc0f6325517170b
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / listeners / VlanMemberConfigListener.java
1 /*
2  * Copyright (c) 2016, 2017 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 java.util.Objects;
11 import javax.inject.Inject;
12 import javax.inject.Singleton;
13 import org.apache.aries.blueprint.annotation.service.Reference;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
16 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
17 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
18 import org.opendaylight.genius.interfacemanager.IfmConstants;
19 import org.opendaylight.genius.interfacemanager.IfmUtil;
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.infrautils.jobcoordinator.JobCoordinator;
24 import org.opendaylight.mdsal.binding.api.DataBroker;
25 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
26 import org.opendaylight.serviceutils.tools.listener.AbstractSyncDataTreeChangeListener;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
31 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 @Singleton
36 public class VlanMemberConfigListener extends AbstractSyncDataTreeChangeListener<Interface> {
37
38     private static final Logger LOG = LoggerFactory.getLogger(VlanMemberConfigListener.class);
39
40     private final JobCoordinator coordinator;
41     private final OvsVlanMemberConfigAddHelper ovsVlanMemberConfigAddHelper;
42     private final OvsVlanMemberConfigRemoveHelper ovsVlanMemberConfigRemoveHelper;
43     private final OvsVlanMemberConfigUpdateHelper ovsVlanMemberConfigUpdateHelper;
44     private final DataTreeEventCallbackRegistrar eventCallbacks;
45     private final ManagedNewTransactionRunner txRunner;
46
47     @Inject
48     public VlanMemberConfigListener(@Reference final DataBroker dataBroker,
49             @Reference final JobCoordinator coordinator,
50             final OvsVlanMemberConfigAddHelper ovsVlanMemberConfigAddHelper,
51             final OvsVlanMemberConfigRemoveHelper ovsVlanMemberConfigRemoveHelper,
52             final OvsVlanMemberConfigUpdateHelper ovsVlanMemberConfigUpdateHelper,
53             @Reference final DataTreeEventCallbackRegistrar eventCallbacks) {
54         super(dataBroker, LogicalDatastoreType.CONFIGURATION,
55               InstanceIdentifier.create(Interfaces.class).child(Interface.class));
56         this.coordinator = coordinator;
57         this.ovsVlanMemberConfigAddHelper = ovsVlanMemberConfigAddHelper;
58         this.ovsVlanMemberConfigRemoveHelper = ovsVlanMemberConfigRemoveHelper;
59         this.ovsVlanMemberConfigUpdateHelper = ovsVlanMemberConfigUpdateHelper;
60         this.eventCallbacks = eventCallbacks;
61         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
62     }
63
64     @Override
65     public void remove(@NonNull InstanceIdentifier<Interface> instanceIdentifier, @NonNull Interface removedInterface) {
66         IfL2vlan ifL2vlan = removedInterface.augmentation(IfL2vlan.class);
67         if (ifL2vlan == null || IfL2vlan.L2vlanMode.TrunkMember != ifL2vlan.getL2vlanMode()) {
68             return;
69         }
70         removeVlanMember(removedInterface);
71     }
72
73     private void removeVlanMember(Interface removedInterface) {
74         ParentRefs parentRefs = removedInterface.augmentation(ParentRefs.class);
75         if (parentRefs == null) {
76             LOG.error("Attempt to remove Vlan Trunk-Member {} without a parent interface", removedInterface);
77             return;
78         }
79
80         String lowerLayerIf = parentRefs.getParentInterface();
81         if (Objects.equals(lowerLayerIf, removedInterface.getName())) {
82             LOG.error("Attempt to remove Vlan Trunk-Member {} with same parent interface name.", removedInterface);
83             return;
84         }
85         coordinator.enqueueJob(lowerLayerIf,
86             () -> ovsVlanMemberConfigRemoveHelper.removeConfiguration(parentRefs, removedInterface),
87                                IfmConstants.JOB_MAX_RETRIES);
88     }
89
90     @Override
91     public void update(@NonNull InstanceIdentifier<Interface> instanceIdentifier,
92                        @NonNull Interface originalInterface, @NonNull Interface updatedInterface) {
93         IfL2vlan ifL2vlanNew = updatedInterface.augmentation(IfL2vlan.class);
94         if (ifL2vlanNew == null) {
95             return;
96         }
97         IfL2vlan ifL2vlanOld = originalInterface.augmentation(IfL2vlan.class);
98         if (IfL2vlan.L2vlanMode.TrunkMember == ifL2vlanNew.getL2vlanMode()
99                 && IfL2vlan.L2vlanMode.Trunk == ifL2vlanOld.getL2vlanMode()) {
100             // Trunk subport add use case
101             addVlanMember(updatedInterface);
102             return;
103         } else if (IfL2vlan.L2vlanMode.Trunk == ifL2vlanNew.getL2vlanMode()
104                 && IfL2vlan.L2vlanMode.TrunkMember == ifL2vlanOld.getL2vlanMode()) {
105             // Trunk subport remove use case
106             removeVlanMember(originalInterface);
107             return;
108         } else if (IfL2vlan.L2vlanMode.TrunkMember != ifL2vlanNew.getL2vlanMode()) {
109             return;
110         }
111
112         ParentRefs parentRefsNew = updatedInterface.augmentation(ParentRefs.class);
113         if (parentRefsNew == null) {
114             LOG.error("Configuration Error. Attempt to update Vlan Trunk-Member {} without a " + "parent interface",
115                       updatedInterface);
116             return;
117         }
118
119         String lowerLayerIf = parentRefsNew.getParentInterface();
120         if (Objects.equals(lowerLayerIf, updatedInterface.getName())) {
121             LOG.error(
122                     "Configuration Error. Attempt to update Vlan Trunk-Member {} with same parent " + "interface name.",
123                     updatedInterface);
124             return;
125         }
126         coordinator.enqueueJob(lowerLayerIf, () -> ovsVlanMemberConfigUpdateHelper
127                                        .updateConfiguration(parentRefsNew, originalInterface, ifL2vlanNew,
128                                                             updatedInterface),
129                                IfmConstants.JOB_MAX_RETRIES);
130     }
131
132     @Override
133     public void add(@NonNull InstanceIdentifier<Interface> instanceIdentifier,
134                     @NonNull Interface newInterface) {
135         IfL2vlan ifL2vlan = newInterface.augmentation(IfL2vlan.class);
136         if (ifL2vlan == null || IfL2vlan.L2vlanMode.TrunkMember != ifL2vlan.getL2vlanMode()) {
137             return;
138         }
139         addVlanMember(newInterface);
140     }
141
142     private void addVlanMember(Interface added) {
143         ParentRefs parentRefs = added.augmentation(ParentRefs.class);
144         if (parentRefs == null) {
145             return;
146         }
147
148         String lowerLayerIf = parentRefs.getParentInterface();
149         if (Objects.equals(lowerLayerIf, added.getName())) {
150             LOG.error("Attempt to add Vlan Trunk-Member {} with same parent interface name.", added);
151             return;
152         }
153
154         LOG.info("registering callback on interface-state for {} for proceeding with "
155                 + "vlan member configuration for interface {}", lowerLayerIf, added.getName());
156         eventCallbacks.onAddOrUpdate(LogicalDatastoreType.OPERATIONAL,
157                 IfmUtil.buildStateInterfaceId(parentRefs.getParentInterface()), (unused, alsoUnused) -> {
158                 LOG.info("parent interface configuration {} detected for l2vlan-member {},"
159                     + "proceeding with state creation", parentRefs.getParentInterface(), added.getName());
160                 ovsVlanMemberConfigAddHelper.addConfiguration(parentRefs, added);
161                 return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
162             });
163     }
164 }