MDSAL-API Migration
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / listeners / InterfaceConfigListener.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
9 package org.opendaylight.genius.interfacemanager.listeners;
10
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.interfacemanager.IfmConstants;
16 import org.opendaylight.genius.interfacemanager.InterfacemgrProvider;
17 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
18 import org.opendaylight.genius.interfacemanager.recovery.impl.InterfaceServiceRecoveryHandler;
19 import org.opendaylight.genius.interfacemanager.renderer.ovs.confighelpers.OvsInterfaceConfigAddHelper;
20 import org.opendaylight.genius.interfacemanager.renderer.ovs.confighelpers.OvsInterfaceConfigRemoveHelper;
21 import org.opendaylight.genius.interfacemanager.renderer.ovs.confighelpers.OvsInterfaceConfigUpdateHelper;
22 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils;
23 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
24 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
25 import org.opendaylight.mdsal.binding.api.DataBroker;
26 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
27 import org.opendaylight.serviceutils.srm.RecoverableListener;
28 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
29 import org.opendaylight.serviceutils.tools.listener.AbstractClusteredSyncDataTreeChangeListener;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * This class listens for interface creation/removal/update in Configuration DS.
40  * This is used to handle interfaces for base of-ports.
41  */
42 @Singleton
43 public class InterfaceConfigListener
44         extends AbstractClusteredSyncDataTreeChangeListener<Interface>
45         implements RecoverableListener {
46
47     private static final Logger LOG = LoggerFactory.getLogger(InterfaceConfigListener.class);
48
49     private final InterfacemgrProvider interfaceMgrProvider;
50     private final EntityOwnershipUtils entityOwnershipUtils;
51     private final JobCoordinator coordinator;
52     private final InterfaceManagerCommonUtils interfaceManagerCommonUtils;
53     private final OvsInterfaceConfigRemoveHelper ovsInterfaceConfigRemoveHelper;
54     private final OvsInterfaceConfigAddHelper ovsInterfaceConfigAddHelper;
55     private final OvsInterfaceConfigUpdateHelper ovsInterfaceConfigUpdateHelper;
56
57     @Inject
58     public InterfaceConfigListener(@Reference DataBroker dataBroker,
59                                    InterfacemgrProvider interfaceMgrProvider,
60                                    EntityOwnershipUtils entityOwnershipUtils,
61                                    @Reference JobCoordinator coordinator,
62                                    InterfaceManagerCommonUtils interfaceManagerCommonUtils,
63                                    OvsInterfaceConfigRemoveHelper ovsInterfaceConfigRemoveHelper,
64                                    OvsInterfaceConfigAddHelper ovsInterfaceConfigAddHelper,
65                                    OvsInterfaceConfigUpdateHelper ovsInterfaceConfigUpdateHelper,
66                                    InterfaceServiceRecoveryHandler interfaceServiceRecoveryHandler,
67                                    @Reference ServiceRecoveryRegistry serviceRecoveryRegistry) {
68         super(dataBroker, LogicalDatastoreType.CONFIGURATION,
69               InstanceIdentifier.create(Interfaces.class).child(Interface.class));
70         this.interfaceMgrProvider = interfaceMgrProvider;
71         this.entityOwnershipUtils = entityOwnershipUtils;
72         this.coordinator = coordinator;
73         this.interfaceManagerCommonUtils = interfaceManagerCommonUtils;
74         this.ovsInterfaceConfigRemoveHelper = ovsInterfaceConfigRemoveHelper;
75         this.ovsInterfaceConfigAddHelper = ovsInterfaceConfigAddHelper;
76         this.ovsInterfaceConfigUpdateHelper = ovsInterfaceConfigUpdateHelper;
77         serviceRecoveryRegistry.addRecoverableListener(interfaceServiceRecoveryHandler.buildServiceRegistryKey(),
78                 this);
79     }
80
81     @Override
82     public void registerListener() {
83         super.register();
84     }
85
86     @Override
87     public void deregisterListener() {
88         close();
89     }
90
91     @Override
92     public void remove(@NonNull InstanceIdentifier<Interface> instanceIdentifier, @NonNull Interface removedInterface) {
93         interfaceManagerCommonUtils.removeFromInterfaceCache(removedInterface);
94
95         if (!entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
96                 IfmConstants.INTERFACE_CONFIG_ENTITY)) {
97             return;
98         }
99         LOG.debug("Received Interface Remove Event: {}, {}", instanceIdentifier, removedInterface);
100         ParentRefs parentRefs = removedInterface.augmentation(ParentRefs.class);
101         if (parentRefs == null
102                 || parentRefs.getDatapathNodeIdentifier() == null && parentRefs.getParentInterface() == null) {
103             LOG.debug("parent refs not specified for {}", removedInterface.getName());
104             return;
105         }
106         String synchronizationKey = InterfaceManagerCommonUtils.isTunnelInterface(removedInterface)
107             ? removedInterface.getName() : parentRefs.getParentInterface();
108         coordinator.enqueueJob(synchronizationKey,
109             () -> ovsInterfaceConfigRemoveHelper.removeConfiguration(removedInterface, parentRefs),
110             IfmConstants.JOB_MAX_RETRIES);
111     }
112
113     @Override
114     public void update(@NonNull InstanceIdentifier<Interface> instanceIdentifier, @NonNull Interface originalInterface,
115                        @NonNull Interface updatedInterface) {
116         interfaceManagerCommonUtils.addInterfaceToCache(updatedInterface);
117
118         if (!entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
119                 IfmConstants.INTERFACE_CONFIG_ENTITY)) {
120             return;
121         }
122         LOG.debug("Received Interface Update Event: {}, {}, {}", instanceIdentifier, originalInterface,
123                   updatedInterface);
124         ParentRefs parentRefs = updatedInterface.augmentation(ParentRefs.class);
125         if (parentRefs == null || parentRefs.getParentInterface() == null) {
126             // If parentRefs are missing, try to find a matching parent and
127             // update - this will trigger another DCN
128             updateInterfaceParentRefs(updatedInterface);
129         }
130
131         if (parentRefs == null
132                 || parentRefs.getDatapathNodeIdentifier() == null && parentRefs.getParentInterface() == null) {
133             LOG.debug("parent refs not specified for {}, or parentRefs {} missing DPN/parentInterface",
134                     updatedInterface.getName(), parentRefs);
135             return;
136         }
137         String synchronizationKey = getSynchronizationKey(updatedInterface, parentRefs);
138         coordinator.enqueueJob(synchronizationKey, () -> ovsInterfaceConfigUpdateHelper
139                 .updateConfiguration(updatedInterface, originalInterface), IfmConstants.JOB_MAX_RETRIES);
140     }
141
142     @Override
143     public void add(@NonNull InstanceIdentifier<Interface> instanceIdentifier, @NonNull Interface newInterface) {
144         interfaceManagerCommonUtils.addInterfaceToCache(newInterface);
145
146         if (!entityOwnershipUtils.isEntityOwner(IfmConstants.INTERFACE_CONFIG_ENTITY,
147                 IfmConstants.INTERFACE_CONFIG_ENTITY)) {
148             return;
149         }
150         LOG.debug("Received Interface Add Event: {}, {}", instanceIdentifier, newInterface);
151         ParentRefs parentRefs = newInterface.augmentation(ParentRefs.class);
152         if (parentRefs == null || parentRefs.getParentInterface() == null) {
153             // If parentRefs are missing, try to find a matching parent and
154             // update - this will trigger another DCN
155             updateInterfaceParentRefs(newInterface);
156         }
157
158         if (parentRefs == null
159                 || parentRefs.getDatapathNodeIdentifier() == null && parentRefs.getParentInterface() == null) {
160             LOG.debug("parent refs not specified for {}", newInterface.getName());
161             return;
162         }
163         String synchronizationKey = getSynchronizationKey(newInterface, parentRefs);
164         coordinator.enqueueJob(synchronizationKey,
165             () -> ovsInterfaceConfigAddHelper.addConfiguration(parentRefs, newInterface),
166             IfmConstants.JOB_MAX_RETRIES);
167     }
168
169     private void updateInterfaceParentRefs(Interface iface) {
170         if (InterfaceManagerCommonUtils.isTunnelInterface(iface)) {
171             return; // update of parent refs is needed only for vm ports, and not tunnels
172         }
173         String ifName = iface.getName();
174         // try to acquire the parent interface name from Southbound
175         String parentRefName = interfaceMgrProvider.getParentRefNameForInterface(ifName);
176         if (parentRefName == null) {
177             LOG.debug("parent refs not specified for {}, failed acquiring it from southbound", ifName);
178             return;
179         }
180         LOG.debug("retrieved parent ref {} for interface {} from southbound, updating parentRef in datastore",
181                   parentRefName, ifName);
182         interfaceMgrProvider.updateInterfaceParentRef(ifName, parentRefName, false);
183     }
184
185     private String getSynchronizationKey(Interface theInterface, ParentRefs theParentRefs) {
186         if (InterfaceManagerCommonUtils.isOfTunnelInterface(theInterface)) {
187             return SouthboundUtils.generateOfTunnelName(
188                     theParentRefs.getDatapathNodeIdentifier(),
189                     theInterface.augmentation(IfTunnel.class));
190         } else if (InterfaceManagerCommonUtils.isTunnelInterface(theInterface)) {
191             return theInterface.getName();
192         } else {
193             return theParentRefs.getParentInterface();
194         }
195     }
196 }