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