Remove deprecated CheckedFuture
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / InterfacemgrProvider.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;
9
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.concurrent.Callable;
17 import java.util.concurrent.ConcurrentHashMap;
18 import java.util.concurrent.ExecutionException;
19 import java.util.concurrent.Future;
20 import javax.annotation.PostConstruct;
21 import javax.annotation.PreDestroy;
22 import javax.inject.Inject;
23 import javax.inject.Singleton;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
26 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
29 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
30 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
31 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
32 import org.opendaylight.genius.interfacemanager.commons.InterfaceMetaUtils;
33 import org.opendaylight.genius.interfacemanager.exceptions.InterfaceAlreadyExistsException;
34 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
35 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo.InterfaceAdminState;
36 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
37 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.BatchingUtils;
38 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.IfmClusterUtils;
39 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.SouthboundUtils;
40 import org.opendaylight.genius.interfacemanager.rpcservice.InterfaceManagerRpcService;
41 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
42 import org.opendaylight.genius.interfacemanager.statusanddiag.InterfaceStatusMonitor;
43 import org.opendaylight.genius.mdsalutil.ActionInfo;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info.InterfaceParentEntry;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.child.info._interface.parent.entry.InterfaceChildEntry;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfExternal;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfExternalBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEndpointIpForDpnInput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEndpointIpForDpnInputBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEndpointIpForDpnOutput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInputBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceOutput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
82 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
83 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
84 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
85 import org.opendaylight.yangtools.yang.common.RpcResult;
86 import org.slf4j.Logger;
87 import org.slf4j.LoggerFactory;
88
89 @Singleton
90 public class InterfacemgrProvider implements AutoCloseable, IInterfaceManager {
91     private static final Logger LOG = LoggerFactory.getLogger(InterfacemgrProvider.class);
92     private static final InterfaceStatusMonitor INTERFACE_STATUS_MONITOR = InterfaceStatusMonitor.getInstance();
93     private final DataBroker dataBroker;
94     private final IdManagerService idManager;
95     private final InterfaceManagerRpcService interfaceManagerRpcService;
96     private final EntityOwnershipService entityOwnershipService;
97     private Map<String, OvsdbTerminationPointAugmentation> ifaceToTpMap;
98     private Map<String, InstanceIdentifier<Node>> ifaceToNodeIidMap;
99     private Map<InstanceIdentifier<Node>, OvsdbBridgeAugmentation> nodeIidToBridgeMap;
100
101     @Inject
102     public InterfacemgrProvider(final DataBroker dataBroker, final EntityOwnershipService entityOwnershipService,
103             final IdManagerService idManager, final InterfaceManagerRpcService interfaceManagerRpcService) {
104         this.dataBroker = dataBroker;
105         this.entityOwnershipService = entityOwnershipService;
106         this.idManager = idManager;
107         this.interfaceManagerRpcService = interfaceManagerRpcService;
108     }
109
110     @PostConstruct
111     @SuppressWarnings("checkstyle:IllegalCatch")
112     public void start() {
113         try {
114             INTERFACE_STATUS_MONITOR.registerMbean();
115             createIdPool();
116             IfmClusterUtils.registerEntityForOwnership(this, this.entityOwnershipService);
117             BatchingUtils.registerWithBatchManager(this.dataBroker);
118             this.ifaceToTpMap = new ConcurrentHashMap<>();
119             this.ifaceToNodeIidMap = new ConcurrentHashMap<>();
120             this.nodeIidToBridgeMap = new ConcurrentHashMap<>();
121
122             INTERFACE_STATUS_MONITOR.reportStatus("OPERATIONAL");
123         } catch (Exception e) {
124             INTERFACE_STATUS_MONITOR.reportStatus("ERROR");
125             throw e;
126         }
127         LOG.info("InterfacemgrProvider Started");
128     }
129
130     @Override
131     @PreDestroy
132     public void close() throws Exception {
133         INTERFACE_STATUS_MONITOR.unregisterMbean();
134         LOG.info("InterfacemgrProvider Closed");
135     }
136
137     public EntityOwnershipService getEntityOwnershipService() {
138         return entityOwnershipService;
139     }
140
141     public DataBroker getDataBroker() {
142         return this.dataBroker;
143     }
144
145     private void createIdPool() {
146         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder().setPoolName(IfmConstants.IFM_IDPOOL_NAME)
147                 .setLow(IfmConstants.IFM_ID_POOL_START).setHigh(IfmConstants.IFM_ID_POOL_END).build();
148         // TODO: Error handling
149         Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
150         try {
151             if (result != null && result.get().isSuccessful()) {
152                 LOG.debug("Created IdPool for InterfaceMgr");
153             }
154         } catch (InterruptedException | ExecutionException e) {
155             LOG.error("Failed to create idPool for InterfaceMgr", e);
156         }
157     }
158
159     @Override
160     public Long getPortForInterface(String ifName) {
161         GetPortFromInterfaceInput input = new GetPortFromInterfaceInputBuilder().setIntfName(ifName).build();
162         Future<RpcResult<GetPortFromInterfaceOutput>> output = interfaceManagerRpcService.getPortFromInterface(input);
163         try {
164             RpcResult<GetPortFromInterfaceOutput> port = output.get();
165             if (port.isSuccessful()) {
166                 return port.getResult().getPortno();
167             }
168         } catch (NullPointerException | InterruptedException | ExecutionException e) {
169             LOG.warn("Exception when getting port for interface", e);
170         }
171         return null;
172     }
173
174     @Override
175     public Long getPortForInterface(Interface intf) {
176         GetPortFromInterfaceInput input = new GetPortFromInterfaceInputBuilder().setIntfName(intf.getName()).build();
177         Future<RpcResult<GetPortFromInterfaceOutput>> output = interfaceManagerRpcService.getPortFromInterface(input);
178         try {
179             RpcResult<GetPortFromInterfaceOutput> port = output.get();
180             if (port.isSuccessful()) {
181                 return port.getResult().getPortno();
182             }
183         } catch (NullPointerException | InterruptedException | ExecutionException e) {
184             LOG.warn("Exception when getting port for interface", e);
185         }
186         return null;
187     }
188
189     @Override
190     public InterfaceInfo getInterfaceInfo(String interfaceName) {
191
192         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
193             .ietf.interfaces.rev140508.interfaces.state.Interface ifState = InterfaceManagerCommonUtils
194                 .getInterfaceState(interfaceName, dataBroker);
195
196         if (ifState == null) {
197             LOG.error("Interface {} is not present", interfaceName);
198             return null;
199         }
200
201         Interface intf = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName),
202                 dataBroker);
203         if (intf == null) {
204             LOG.error("Interface {} doesn't exist in config datastore", interfaceName);
205             return null;
206         }
207
208         NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(intf.getName(), dataBroker);
209         InterfaceInfo.InterfaceType interfaceType = IfmUtil.getInterfaceType(intf);
210         InterfaceInfo interfaceInfo = new InterfaceInfo(interfaceName);
211         BigInteger dpId = org.opendaylight.genius.interfacemanager.globals.IfmConstants.INVALID_DPID;
212         Integer portNo = org.opendaylight.genius.interfacemanager.globals.IfmConstants.INVALID_PORT_NO;
213         if (ncId != null) {
214             dpId = IfmUtil.getDpnFromNodeConnectorId(ncId);
215             portNo = Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId));
216         }
217         if (interfaceType == InterfaceInfo.InterfaceType.VLAN_INTERFACE) {
218             interfaceInfo = IfmUtil.getVlanInterfaceInfo(interfaceName, intf, dpId);
219         } else if (interfaceType == InterfaceInfo.InterfaceType.UNKNOWN_INTERFACE) {
220             LOG.error("Type of Interface {} is unknown", interfaceName);
221             return null;
222         }
223         InterfaceInfo.InterfaceOpState opState;
224         if (ifState.getOperStatus() == OperStatus.Up) {
225             opState = InterfaceInfo.InterfaceOpState.UP;
226         } else if (ifState.getOperStatus() == OperStatus.Down) {
227             opState = InterfaceInfo.InterfaceOpState.DOWN;
228         } else {
229             opState = InterfaceInfo.InterfaceOpState.UNKNOWN;
230         }
231         interfaceInfo.setDpId(dpId);
232         interfaceInfo.setPortNo(portNo);
233         interfaceInfo.setAdminState(intf.isEnabled() ? InterfaceAdminState.ENABLED : InterfaceAdminState.DISABLED);
234         interfaceInfo.setInterfaceName(interfaceName);
235         Integer lportTag = ifState.getIfIndex();
236         interfaceInfo.setInterfaceTag(lportTag);
237         interfaceInfo.setInterfaceType(interfaceType);
238         interfaceInfo.setGroupId(IfmUtil.getGroupId(lportTag, interfaceType));
239         interfaceInfo.setOpState(opState);
240         PhysAddress phyAddress = ifState.getPhysAddress();
241         if (phyAddress != null) {
242             interfaceInfo.setMacAddress(ifState.getPhysAddress().getValue());
243         }
244
245         return interfaceInfo;
246
247     }
248
249     @Override
250     public InterfaceInfo getInterfaceInfoFromOperationalDataStore(String interfaceName,
251             InterfaceInfo.InterfaceType interfaceType) {
252         InterfaceInfo interfaceInfo = new InterfaceInfo(interfaceName);
253         org.opendaylight.yang.gen.v1.urn
254             .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
255                 InterfaceManagerCommonUtils
256                 .getInterfaceState(interfaceName, dataBroker);
257         if (ifState == null) {
258             LOG.error("Interface {} is not present", interfaceName);
259             return null;
260         }
261         NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(ifState);
262         if (ncId != null) {
263             interfaceInfo.setDpId(IfmUtil.getDpnFromNodeConnectorId(ncId));
264             interfaceInfo.setPortNo(Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId)));
265         }
266         InterfaceInfo.InterfaceOpState opState;
267         if (ifState.getOperStatus() == OperStatus.Up) {
268             opState = InterfaceInfo.InterfaceOpState.UP;
269         } else if (ifState.getOperStatus() == OperStatus.Down) {
270             opState = InterfaceInfo.InterfaceOpState.DOWN;
271         } else {
272             opState = InterfaceInfo.InterfaceOpState.UNKNOWN;
273         }
274         interfaceInfo.setAdminState(ifState.getAdminStatus() == AdminStatus.Up ? InterfaceAdminState.ENABLED
275                 : InterfaceAdminState.DISABLED);
276         interfaceInfo.setInterfaceName(interfaceName);
277         Integer lportTag = ifState.getIfIndex();
278         interfaceInfo.setInterfaceTag(lportTag);
279         interfaceInfo.setInterfaceType(interfaceType);
280         interfaceInfo.setGroupId(IfmUtil.getGroupId(lportTag, interfaceType));
281         interfaceInfo.setOpState(opState);
282         PhysAddress phyAddress = ifState.getPhysAddress();
283         if (phyAddress != null) {
284             interfaceInfo.setMacAddress(ifState.getPhysAddress().getValue());
285         }
286         return interfaceInfo;
287     }
288
289     @Override
290     public InterfaceInfo getInterfaceInfoFromOperationalDataStore(String interfaceName) {
291         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
292             .ietf.interfaces.rev140508.interfaces.state.Interface ifState = InterfaceManagerCommonUtils
293                 .getInterfaceState(interfaceName, dataBroker);
294         if (ifState == null) {
295             LOG.error("Interface {} is not present", interfaceName);
296             return null;
297         }
298
299         return populateInterfaceInfo(interfaceName, ifState);
300     }
301
302     public InterfaceInfo populateInterfaceInfo(String interfaceName,
303             org.opendaylight.yang.gen.v1.urn
304                 .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
305         InterfaceInfo interfaceInfo = new InterfaceInfo(interfaceName);
306         NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(ifState);
307         if (ncId != null) {
308             if (Tunnel.class.equals(ifState.getType())) {
309                 interfaceInfo.setPortName(interfaceName);
310             } else {
311                 Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
312                 if (iface != null) {
313                     ParentRefs parentRefs = iface.getAugmentation(ParentRefs.class);
314                     interfaceInfo.setPortName(parentRefs.getParentInterface());
315                 }
316             }
317             interfaceInfo.setDpId(IfmUtil.getDpnFromNodeConnectorId(ncId));
318             interfaceInfo.setPortNo(Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId)));
319         }
320         InterfaceInfo.InterfaceOpState opState;
321         if (ifState.getOperStatus() == OperStatus.Up) {
322             opState = InterfaceInfo.InterfaceOpState.UP;
323         } else if (ifState.getOperStatus() == OperStatus.Down) {
324             opState = InterfaceInfo.InterfaceOpState.DOWN;
325         } else {
326             opState = InterfaceInfo.InterfaceOpState.UNKNOWN;
327         }
328         interfaceInfo.setAdminState(ifState.getAdminStatus() == AdminStatus.Up ? InterfaceAdminState.ENABLED
329                 : InterfaceAdminState.DISABLED);
330         interfaceInfo.setInterfaceName(interfaceName);
331         Integer lportTag = ifState.getIfIndex();
332         if (lportTag != null) {
333             interfaceInfo.setInterfaceTag(lportTag);
334         }
335         interfaceInfo.setOpState(opState);
336         PhysAddress phyAddress = ifState.getPhysAddress();
337         if (phyAddress != null) {
338             interfaceInfo.setMacAddress(ifState.getPhysAddress().getValue());
339         }
340         return interfaceInfo;
341     }
342
343     @Override
344     public InterfaceInfo getInterfaceInfoFromOperationalDSCache(String interfaceName) {
345         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
346             .ietf.interfaces.rev140508.interfaces.state.Interface ifState = InterfaceManagerCommonUtils
347                 .getInterfaceStateFromCache(interfaceName);
348         if (ifState == null) {
349             LOG.warn("Interface {} is not present", interfaceName);
350             return null;
351         }
352         return populateInterfaceInfo(interfaceName, ifState);
353     }
354
355     @Override
356     public Interface getInterfaceInfoFromConfigDataStore(String interfaceName) {
357         return InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName), dataBroker);
358     }
359
360     @Override
361     public void createVLANInterface(String interfaceName, String portName, BigInteger dpId, Integer vlanId,
362             String description, IfL2vlan.L2vlanMode l2vlanMode) throws InterfaceAlreadyExistsException {
363         createVLANInterface(interfaceName, portName, dpId, vlanId, description, l2vlanMode, false);
364     }
365
366     @Override
367     public void createVLANInterface(String interfaceName, String portName, BigInteger dpId, Integer vlanId,
368             String description, IfL2vlan.L2vlanMode l2vlanMode, boolean isExternal)
369             throws InterfaceAlreadyExistsException {
370
371         LOG.info("Create VLAN interface : {}", interfaceName);
372         Interface interfaceOptional = InterfaceManagerCommonUtils
373                 .getInterfaceFromConfigDS(new InterfaceKey(interfaceName), dataBroker);
374         if (interfaceOptional != null) {
375             LOG.debug("VLAN interface is already exist", interfaceOptional.getDescription());
376             throw new InterfaceAlreadyExistsException(interfaceOptional.getName());
377         }
378         IfL2vlanBuilder l2vlanBuilder = new IfL2vlanBuilder().setL2vlanMode(l2vlanMode);
379         if (vlanId != null && vlanId > 0) {
380             l2vlanBuilder.setVlanId(new VlanId(vlanId));
381         }
382         ParentRefs parentRefs = new ParentRefsBuilder().setParentInterface(portName).build();
383         InterfaceBuilder interfaceBuilder = new InterfaceBuilder().setEnabled(true).setName(interfaceName)
384                 .setType(L2vlan.class).addAugmentation(IfL2vlan.class, l2vlanBuilder.build())
385                 .addAugmentation(ParentRefs.class, parentRefs).setDescription(description);
386         if (isExternal) {
387             interfaceBuilder.addAugmentation(IfExternal.class, new IfExternalBuilder().setExternal(true).build());
388         }
389         InstanceIdentifier<Interface> interfaceInstanceIdentifier = InterfaceManagerCommonUtils
390                 .getInterfaceIdentifier(new InterfaceKey(interfaceName));
391         WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
392         writeTransaction.put(LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier, interfaceBuilder.build(),
393                 true);
394         writeTransaction.submit();
395     }
396
397     private boolean isServiceBoundOnInterface(short servicePriority, String interfaceName,
398             Class<? extends ServiceModeBase> serviceMode) {
399         InstanceIdentifier<BoundServices> boundServicesIId = IfmUtil.buildBoundServicesIId(servicePriority,
400                 interfaceName, serviceMode);
401         try {
402             return SingleTransactionDataBroker
403                     .syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, boundServicesIId).isPresent();
404         } catch (ReadFailedException e) {
405             LOG.warn("Error while reading [{}]", boundServicesIId, e);
406             return false;
407         }
408     }
409
410     @Override
411     public boolean isServiceBoundOnInterfaceForIngress(short servicePriority, String interfaceName) {
412         return isServiceBoundOnInterface(servicePriority, interfaceName, ServiceModeIngress.class);
413     }
414
415     @Override
416     public boolean isServiceBoundOnInterfaceForEgress(short servicePriority, String interfaceName) {
417         return isServiceBoundOnInterface(servicePriority, interfaceName, ServiceModeEgress.class);
418     }
419
420     @Override
421     public void bindService(String interfaceName, Class<? extends ServiceModeBase> serviceMode,
422             BoundServices serviceInfo) {
423         bindService(interfaceName, serviceMode, serviceInfo, /* WriteTransaction */ null);
424     }
425
426     @Override
427     public void bindService(String interfaceName, Class<? extends ServiceModeBase> serviceMode,
428             BoundServices serviceInfo, WriteTransaction tx) {
429         WriteTransaction writeTransaction = tx != null ? tx : dataBroker.newWriteOnlyTransaction();
430         IfmUtil.bindService(writeTransaction, interfaceName, serviceInfo, serviceMode);
431         if (tx == null) {
432             writeTransaction.submit();
433         }
434     }
435
436     @Override
437     public void unbindService(String interfaceName, Class<? extends ServiceModeBase> serviceMode,
438             BoundServices serviceInfo) {
439         IfmUtil.unbindService(dataBroker, interfaceName,
440                 FlowBasedServicesUtils.buildServiceId(interfaceName, serviceInfo.getServicePriority(), serviceMode));
441     }
442
443     @Override
444     public BigInteger getDpnForInterface(Interface intrf) {
445         return getDpnForInterface(intrf.getName());
446     }
447
448     @Override
449     public BigInteger getDpnForInterface(String ifName) {
450         GetDpidFromInterfaceInput input = new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
451         Future<RpcResult<GetDpidFromInterfaceOutput>> output = interfaceManagerRpcService.getDpidFromInterface(input);
452         try {
453             RpcResult<GetDpidFromInterfaceOutput> dpn = output.get();
454             if (dpn.isSuccessful()) {
455                 return dpn.getResult().getDpid();
456             }
457         } catch (NullPointerException | InterruptedException | ExecutionException e) {
458             LOG.warn("Exception when getting port for interface", e);
459         }
460         return null;
461     }
462
463     @Override
464     public String getEndpointIpForDpn(BigInteger dpnId) {
465         GetEndpointIpForDpnInput input = new GetEndpointIpForDpnInputBuilder().setDpid(dpnId).build();
466         Future<RpcResult<GetEndpointIpForDpnOutput>> output = interfaceManagerRpcService.getEndpointIpForDpn(input);
467         try {
468             RpcResult<GetEndpointIpForDpnOutput> ipForDpnOutputRpcResult = output.get();
469             if (ipForDpnOutputRpcResult.isSuccessful()) {
470                 List<IpAddress> localIps = ipForDpnOutputRpcResult.getResult().getLocalIps();
471                 if (!localIps.isEmpty()) {
472                     return localIps.get(0).getIpv4Address().getValue();
473                 }
474             }
475         } catch (NullPointerException | InterruptedException | ExecutionException e) {
476             LOG.warn("Exception when getting port for interface", e);
477         }
478         return null;
479     }
480
481     @Override
482     public List<ActionInfo> getInterfaceEgressActions(String ifName) {
483         return IfmUtil.getEgressActionInfosForInterface(ifName, 0, dataBroker, false);
484     }
485
486     @Override
487     public List<Interface> getVlanInterfaces() {
488         return InterfaceManagerCommonUtils.getAllVlanInterfacesFromCache();
489     }
490
491     @Override
492     public List<Interface> getVxlanInterfaces() {
493         return InterfaceManagerCommonUtils.getAllTunnelInterfacesFromCache();
494     }
495
496     @Override
497     public List<Interface> getChildInterfaces(String parentInterface) {
498         InterfaceParentEntry parentEntry = InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(parentInterface,
499                 dataBroker);
500         if (parentEntry == null) {
501             LOG.debug("No parent entry found for {}", parentInterface);
502             return Collections.emptyList();
503         }
504
505         List<InterfaceChildEntry> childEntries = parentEntry.getInterfaceChildEntry();
506         if (childEntries == null || childEntries.isEmpty()) {
507             LOG.debug("No child entries found for parent {}", parentInterface);
508             return Collections.emptyList();
509         }
510
511         List<Interface> childInterfaces = new ArrayList<>();
512         for (InterfaceChildEntry childEntry : childEntries) {
513             String interfaceName = childEntry.getChildInterface();
514             Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
515             if (iface != null) {
516                 childInterfaces.add(iface);
517             } else {
518                 LOG.debug("Child interface {} not found in config DS for parent interface {}", interfaceName,
519                         parentInterface);
520             }
521         }
522
523         LOG.trace("Found child interfaces {} for parent {}", childInterfaces, parentInterface);
524         return childInterfaces;
525     }
526
527     @Override
528     public boolean isExternalInterface(String interfaceName) {
529         return isExternalInterface(getInterfaceInfoFromConfigDataStore(interfaceName));
530     }
531
532     private boolean isExternalInterface(Interface iface) {
533         if (iface == null) {
534             return false;
535         }
536
537         IfExternal ifExternal = iface.getAugmentation(IfExternal.class);
538         return ifExternal != null && Boolean.TRUE.equals(ifExternal.isExternal());
539     }
540
541     @Override
542     public String getPortNameForInterface(NodeConnectorId nodeConnectorId, String interfaceName) {
543         return InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId, interfaceName);
544     }
545
546     @Override
547     public String getPortNameForInterface(String dpnId, String interfaceName) {
548         return InterfaceManagerCommonUtils.getPortNameForInterface(dpnId, interfaceName);
549     }
550
551     @Override
552     public Map<String, OvsdbTerminationPointAugmentation> getTerminationPointCache() {
553         return new ConcurrentHashMap<>(this.ifaceToTpMap);
554     }
555
556     public void addTerminationPointForInterface(String interfaceName,
557             OvsdbTerminationPointAugmentation terminationPoint) {
558         LOG.debug("Adding TerminationPoint {} to cache for Interface {}", terminationPoint.getName(), interfaceName);
559         if (interfaceName != null && terminationPoint != null) {
560             ifaceToTpMap.put(interfaceName, terminationPoint);
561         }
562     }
563
564     public OvsdbTerminationPointAugmentation getTerminationPoint(String interfaceName) {
565         return ifaceToTpMap.get(interfaceName);
566     }
567
568     public void removeTerminationPointForInterface(String interfaceName) {
569         LOG.debug("Removing TerminationPoint from cache for Interface {}", interfaceName);
570         if (interfaceName != null) {
571             ifaceToTpMap.remove(interfaceName);
572         }
573     }
574
575     public void addNodeIidForInterface(String interfaceName, InstanceIdentifier<Node> nodeIid) {
576         if (interfaceName != null && nodeIid != null) {
577             ifaceToNodeIidMap.put(interfaceName, nodeIid);
578         }
579     }
580
581     public void removeNodeIidForInterface(String interfaceName) {
582         if (interfaceName != null) {
583             ifaceToNodeIidMap.remove(interfaceName);
584         }
585     }
586
587     public InstanceIdentifier<Node> getNodeIidForInterface(String interfaceName) {
588         if (interfaceName != null) {
589             return ifaceToNodeIidMap.get(interfaceName);
590         }
591         return null;
592     }
593
594     private OvsdbBridgeAugmentation getBridgeForInterface(String interfaceName,
595             InstanceIdentifier<Node> nodeInstanceId) {
596         InstanceIdentifier<Node> nodeIid = nodeInstanceId;
597         if (nodeIid == null) {
598             nodeIid = getNodeIidForInterface(interfaceName);
599         }
600         return getBridgeForNodeIid(nodeIid);
601     }
602
603     public String getDpidForInterface(String interfaceName) {
604         return getDpidForInterface(interfaceName, null);
605     }
606
607     public String getDpidForInterface(String interfaceName, InstanceIdentifier<Node> nodeInstanceId) {
608         OvsdbBridgeAugmentation bridge = getBridgeForInterface(interfaceName, nodeInstanceId);
609         if (bridge != null) {
610             BigInteger dpid = IfmUtil.getDpnId(bridge.getDatapathId());
611             if (dpid != null && dpid.longValue() != 0) {
612                 return String.valueOf(dpid);
613             }
614         }
615         return null;
616     }
617
618     public void addBridgeForNodeIid(InstanceIdentifier<Node> nodeIid, OvsdbBridgeAugmentation bridge) {
619         if (nodeIid != null && bridge != null) {
620             nodeIidToBridgeMap.put(nodeIid, bridge);
621         }
622     }
623
624     public void removeBridgeForNodeIid(InstanceIdentifier<Node> nodeIid) {
625         if (nodeIid != null) {
626             nodeIidToBridgeMap.remove(nodeIid);
627         }
628     }
629
630     public OvsdbBridgeAugmentation getBridgeForNodeIid(InstanceIdentifier<Node> nodeIid) {
631         if (nodeIid != null) {
632             return nodeIidToBridgeMap.get(nodeIid);
633         }
634         return null;
635     }
636
637     @Override
638     public String getParentRefNameForInterface(String interfaceName) {
639         String parentRefName = null;
640
641         String dpnId = getDpidForInterface(interfaceName, null);
642         OvsdbTerminationPointAugmentation ovsdbTp = getTerminationPoint(interfaceName);
643         if (ovsdbTp != null) {
644             if (dpnId == null) {
645                 LOG.error("Got NULL dpnId when looking for TP with external ID {}", interfaceName);
646                 return null;
647             }
648             parentRefName = getPortNameForInterface(dpnId, ovsdbTp.getName());
649             LOG.debug("Building parent ref for interface {}, using parentRefName {} acquired by external ID",
650                     interfaceName, parentRefName);
651         } else {
652             LOG.debug("Skipping parent ref for interface {}, as there is no termination point that references "
653                     + "this interface yet.", interfaceName);
654         }
655
656         return parentRefName;
657     }
658
659     @Override
660     public void updateInterfaceParentRef(String interfaceName, String parentInterface) {
661         // This should generally be called by EOS Owner for
662         // INTERFACE_CONFIG_ENTITY - runOnlyInLeaderNode()
663         updateInterfaceParentRef(interfaceName, parentInterface, true);
664     }
665
666     @Override
667     public void updateInterfaceParentRef(String interfaceName, String parentInterface,
668             boolean readInterfaceBeforeWrite) {
669         // This should generally be called by EOS Owner for
670         // INTERFACE_CONFIG_ENTITY - runOnlyInLeaderNode()
671         if (interfaceName == null) {
672             return;
673         }
674
675         DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
676         ParentRefUpdateWorker parentRefUpdateWorker = new ParentRefUpdateWorker(interfaceName, parentInterface,
677                 readInterfaceBeforeWrite);
678         jobCoordinator.enqueueJob(interfaceName, parentRefUpdateWorker, IfmConstants.JOB_MAX_RETRIES);
679     }
680
681     public class ParentRefUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
682         String interfaceName;
683         String parentInterfaceName;
684         Boolean readInterfaceBeforeWrite;
685
686         public ParentRefUpdateWorker(String interfaceName, String parentInterfaceName,
687                 boolean readInterfaceBeforeWrite) {
688             this.interfaceName = interfaceName;
689             this.parentInterfaceName = parentInterfaceName;
690             this.readInterfaceBeforeWrite = readInterfaceBeforeWrite;
691         }
692
693         @Override
694         public List<ListenableFuture<Void>> call() throws Exception {
695             if (readInterfaceBeforeWrite) {
696                 Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
697                 if (iface == null) {
698                     LOG.debug("Interface doesn't exist in config DS - no need to update parentRef, skipping");
699                     return null;
700                 }
701             }
702             WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
703             IfmUtil.updateInterfaceParentRef(writeTransaction, interfaceName, parentInterfaceName);
704             return Collections.singletonList(writeTransaction.submit());
705         }
706     }
707
708     @Override
709     public OvsdbTerminationPointAugmentation getTerminationPointForInterface(String interfaceName) {
710         return getTerminationPoint(interfaceName);
711     }
712
713     @Override
714     public OvsdbBridgeAugmentation getOvsdbBridgeForInterface(String interfaceName) {
715         return getBridgeForInterface(interfaceName, null);
716     }
717
718     @Override
719     public OvsdbBridgeAugmentation getOvsdbBridgeForNodeIid(InstanceIdentifier<Node> nodeIid) {
720         return getBridgeForNodeIid(nodeIid);
721     }
722
723     @Override
724     /**
725      * Get all termination points on a given DPN.
726      * This API uses read on Operational DS. If there are perf issues in cluster
727      * setup, we can consider caching later.
728      *
729      * @param dpnId
730      *            Datapath Node Identifier
731      *
732      * @return If the data at the supplied path exists, returns a list of all termination point
733      *         Augmentations
734      */
735     public List<OvsdbTerminationPointAugmentation> getPortsOnBridge(BigInteger dpnId) {
736         List<OvsdbTerminationPointAugmentation> ports = new ArrayList<>();
737         List<TerminationPoint> portList = IfmUtil.getTerminationPointsOnBridge(dataBroker, dpnId);
738         for (TerminationPoint ovsPort : portList) {
739             if (ovsPort.getAugmentation(OvsdbTerminationPointAugmentation.class) != null) {
740                 ports.add(ovsPort.getAugmentation(OvsdbTerminationPointAugmentation.class));
741             }
742         }
743         LOG.debug("Found {} ports on bridge {}", ports.size(), dpnId);
744         return ports;
745     }
746
747     /**
748      * Get all termination points of type tunnel on a given DPN.
749      *
750      * @param dpnId
751      *            Datapath Node Identifier
752      *
753      * @return If the data at the supplied path exists, returns a list of all termination point
754      *         Augmentations of type tunnel
755      */
756     @Override
757     public List<OvsdbTerminationPointAugmentation> getTunnelPortsOnBridge(BigInteger dpnId) {
758         List<OvsdbTerminationPointAugmentation> tunnelPorts = new ArrayList<>();
759         List<TerminationPoint> portList = IfmUtil.getTerminationPointsOnBridge(dataBroker, dpnId);
760         for (TerminationPoint ovsPort : portList) {
761             OvsdbTerminationPointAugmentation portAug =
762                     ovsPort.getAugmentation(OvsdbTerminationPointAugmentation.class);
763             if (portAug != null && SouthboundUtils.isInterfaceTypeTunnel(portAug.getInterfaceType())) {
764                 tunnelPorts.add(portAug);
765             }
766         }
767
768         LOG.debug("Found {} tunnel ports on bridge {}", tunnelPorts.size(), dpnId);
769         return tunnelPorts;
770     }
771
772     /**
773      * Get all termination points by type on a given DPN.
774      *
775      * @param dpnId
776      *            Datapath Node Identifier
777      *
778      * @return If the data at the supplied path exists, returns a Map where key is interfaceType
779      *         and value is list of termination points of given type
780      */
781     @Override
782     public Map<Class<? extends InterfaceTypeBase>, List<OvsdbTerminationPointAugmentation>>
783         getPortsOnBridgeByType(BigInteger dpnId) {
784
785         Map<Class<? extends InterfaceTypeBase>, List<OvsdbTerminationPointAugmentation>> portMap;
786         portMap = new ConcurrentHashMap<>();
787         List<TerminationPoint> ovsPorts = IfmUtil.getTerminationPointsOnBridge(dataBroker, dpnId);
788         if (ovsPorts != null) {
789             for (TerminationPoint ovsPort : ovsPorts) {
790                 OvsdbTerminationPointAugmentation portAug =
791                         ovsPort.getAugmentation(OvsdbTerminationPointAugmentation.class);
792                 if (portAug != null && portAug.getInterfaceType() != null) {
793                     portMap.computeIfAbsent(portAug.getInterfaceType(), k -> new ArrayList<>()).add(portAug);
794                 }
795             }
796         }
797         return portMap;
798     }
799
800     @Override
801     public long getLogicalTunnelSelectGroupId(int lportTag) {
802         return IfmUtil.getLogicalTunnelSelectGroupId(lportTag);
803     }
804 }