Merge "Fix status-and-diag after BP migration"
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / InterfacemgrProvider.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.genius.interfacemanager;
9
10
11 import com.google.common.util.concurrent.CheckedFuture;
12 import com.google.common.util.concurrent.ListenableFuture;
13
14 import java.math.BigInteger;
15 import java.util.ArrayList;
16 import java.util.List;
17 import java.util.concurrent.Callable;
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.controller.md.sal.common.api.data.TransactionCommitFailedException;
30 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
31 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
32 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
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.rpcservice.InterfaceManagerRpcService;
40 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
41 import org.opendaylight.genius.interfacemanager.servicebindings.flowbased.utilities.FlowBasedServicesUtils.ServiceMode;
42 import org.opendaylight.genius.interfacemanager.statusanddiag.InterfaceStatusMonitor;
43 import org.opendaylight.genius.mdsalutil.ActionInfo;
44 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
45 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfExternal;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfExternalBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEndpointIpForDpnInput;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEndpointIpForDpnInputBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEndpointIpForDpnOutput;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceInputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetPortFromInterfaceOutput;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
85 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
86 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
87 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
88 import org.opendaylight.yangtools.yang.common.RpcResult;
89 import org.slf4j.Logger;
90 import org.slf4j.LoggerFactory;
91
92 @Singleton
93 public class InterfacemgrProvider implements AutoCloseable, IInterfaceManager {
94
95     private static final Logger LOG = LoggerFactory.getLogger(InterfacemgrProvider.class);
96     private static final InterfaceStatusMonitor interfaceStatusMonitor = InterfaceStatusMonitor.getInstance();
97     private final DataBroker dataBroker;
98     private final IdManagerService idManager;
99     private final InterfaceManagerRpcService interfaceManagerRpcService;
100     private final EntityOwnershipService entityOwnershipService;
101     private final MdsalUtils mdsalUtils;
102     private final SouthboundUtils southboundUtils;
103
104     @Inject
105     public InterfacemgrProvider(final DataBroker dataBroker, final EntityOwnershipService entityOwnershipService,
106                                 final IdManagerService idManager,
107                                 final InterfaceManagerRpcService interfaceManagerRpcService){
108         this.dataBroker = dataBroker;
109         this.entityOwnershipService = entityOwnershipService;
110         this.idManager = idManager;
111         this.interfaceManagerRpcService = interfaceManagerRpcService;
112         this.mdsalUtils = new MdsalUtils(dataBroker);
113         this.southboundUtils = new SouthboundUtils(mdsalUtils);
114     }
115
116     @PostConstruct
117     @SuppressWarnings("checkstyle:IllegalCatch")
118     public void start() throws Exception {
119         try {
120             interfaceStatusMonitor.registerMbean();
121             createIdPool();
122             IfmClusterUtils.registerEntityForOwnership(this, this.entityOwnershipService);
123             BatchingUtils.registerWithBatchManager( this.dataBroker);
124             interfaceStatusMonitor.reportStatus("OPERATIONAL");
125         } catch (Exception e) {
126             interfaceStatusMonitor.reportStatus("ERROR");
127             throw e;
128         }
129         LOG.info("InterfacemgrProvider Started");
130     }
131
132     @Override
133     @PreDestroy
134     public void close() throws Exception {
135         LOG.info("InterfacemgrProvider Closed");
136     }
137
138     public EntityOwnershipService getEntityOwnershipService() {
139         return entityOwnershipService;
140     }
141
142     public DataBroker getDataBroker(){
143         return this.dataBroker;
144     }
145
146     private void createIdPool() {
147         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
148                 .setPoolName(IfmConstants.IFM_IDPOOL_NAME)
149                 .setLow(IfmConstants.IFM_ID_POOL_START)
150                 .setHigh(IfmConstants.IFM_ID_POOL_END)
151                 .build();
152         //TODO: Error handling
153         Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
154         try {
155             if (result != null && result.get().isSuccessful()) {
156                 LOG.debug("Created IdPool for InterfaceMgr");
157             }
158         } catch (InterruptedException | ExecutionException e) {
159             LOG.error("Failed to create idPool for InterfaceMgr", e);
160         }
161     }
162
163     @Override
164     public Long getPortForInterface(String ifName) {
165         GetPortFromInterfaceInput input = new GetPortFromInterfaceInputBuilder().setIntfName(ifName).build();
166         Future<RpcResult<GetPortFromInterfaceOutput>> output = interfaceManagerRpcService.getPortFromInterface(input);
167         try {
168             RpcResult<GetPortFromInterfaceOutput> port = output.get();
169             if (port.isSuccessful()) {
170                 return port.getResult().getPortno();
171             }
172         } catch (NullPointerException | InterruptedException | ExecutionException e) {
173             LOG.warn("Exception when getting port for interface", e);
174         }
175         return null;
176     }
177
178     @Override
179     public Long getPortForInterface(Interface intf) {
180         GetPortFromInterfaceInput input = new GetPortFromInterfaceInputBuilder().setIntfName(intf.getName()).build();
181         Future<RpcResult<GetPortFromInterfaceOutput>> output = interfaceManagerRpcService.getPortFromInterface(input);
182         try {
183             RpcResult<GetPortFromInterfaceOutput> port = output.get();
184             if (port.isSuccessful()) {
185                 return port.getResult().getPortno();
186             }
187         } catch (NullPointerException | InterruptedException | ExecutionException e) {
188             LOG.warn("Exception when getting port for interface", e);
189         }
190         return null;
191     }
192
193     @Override
194     public InterfaceInfo getInterfaceInfo(String interfaceName) {
195
196         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
197                 ifState = InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName, dataBroker);
198
199         if (ifState == null) {
200             LOG.error("Interface {} is not present", interfaceName);
201             return null;
202         }
203
204         Integer lportTag = ifState.getIfIndex();
205         Interface intf = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName), dataBroker);
206         if (intf == null) {
207             LOG.error("Interface {} doesn't exist in config datastore", interfaceName);
208             return null;
209         }
210
211         NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(intf.getName(), dataBroker);
212         InterfaceInfo.InterfaceType interfaceType = IfmUtil.getInterfaceType(intf);
213         InterfaceInfo interfaceInfo = new InterfaceInfo(interfaceName);
214         BigInteger dpId = org.opendaylight.genius.interfacemanager.globals.IfmConstants.INVALID_DPID;
215         Integer portNo = org.opendaylight.genius.interfacemanager.globals.IfmConstants.INVALID_PORT_NO;
216         if (ncId != null) {
217             dpId = IfmUtil.getDpnFromNodeConnectorId(ncId);
218             portNo = Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId));
219         }
220         if (interfaceType == InterfaceInfo.InterfaceType.VLAN_INTERFACE) {
221             interfaceInfo = IfmUtil.getVlanInterfaceInfo(interfaceName, intf, dpId);
222         } else if (interfaceType == InterfaceInfo.InterfaceType.VXLAN_TRUNK_INTERFACE ||
223                 interfaceType == InterfaceInfo.InterfaceType.GRE_TRUNK_INTERFACE) {
224             // TODO : since there is no logical grouping for tunnel interfaces, there is no need
225             // for this code as of now. will be revisited once the support comes
226
227         } else {
228             LOG.error("Type of Interface {} is unknown", interfaceName);
229             return null;
230         }
231         InterfaceInfo.InterfaceOpState opState ;
232         if(ifState.getOperStatus() == OperStatus.Up)
233         {
234             opState = InterfaceInfo.InterfaceOpState.UP;
235         }
236         else if (ifState.getOperStatus() == OperStatus.Down)
237         {
238             opState = InterfaceInfo.InterfaceOpState.DOWN;
239         }
240         else
241         {
242             opState = InterfaceInfo.InterfaceOpState.UNKNOWN;
243         }
244         interfaceInfo.setDpId(dpId);
245         interfaceInfo.setPortNo(portNo);
246         interfaceInfo.setAdminState(intf.isEnabled() ? InterfaceAdminState.ENABLED : InterfaceAdminState.DISABLED);
247         interfaceInfo.setInterfaceName(interfaceName);
248         interfaceInfo.setInterfaceTag(lportTag);
249         interfaceInfo.setInterfaceType(interfaceType);
250         interfaceInfo.setGroupId(IfmUtil.getGroupId(lportTag, interfaceType));
251         interfaceInfo.setOpState(opState);
252         PhysAddress phyAddress = ifState.getPhysAddress();
253         if (phyAddress != null) {
254             interfaceInfo.setMacAddress(ifState.getPhysAddress().getValue());
255         }
256
257         return interfaceInfo;
258
259     }
260
261     @Override
262     public InterfaceInfo getInterfaceInfoFromOperationalDataStore(String interfaceName, InterfaceInfo.InterfaceType interfaceType) {
263         InterfaceInfo interfaceInfo = new InterfaceInfo(interfaceName);
264         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState = InterfaceManagerCommonUtils
265                 .getInterfaceStateFromOperDS(interfaceName, dataBroker);
266         if (ifState == null) {
267             LOG.error("Interface {} is not present", interfaceName);
268             return null;
269         }
270         Integer lportTag = ifState.getIfIndex();
271         NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(ifState);
272         if (ncId != null) {
273             interfaceInfo.setDpId(IfmUtil.getDpnFromNodeConnectorId(ncId));
274             interfaceInfo.setPortNo(Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId)));
275         }
276         InterfaceInfo.InterfaceOpState opState ;
277         if(ifState.getOperStatus() == OperStatus.Up)
278         {
279             opState = InterfaceInfo.InterfaceOpState.UP;
280         }
281         else if (ifState.getOperStatus() == OperStatus.Down)
282         {
283             opState = InterfaceInfo.InterfaceOpState.DOWN;
284         }
285         else
286         {
287             opState = InterfaceInfo.InterfaceOpState.UNKNOWN;
288         }
289         interfaceInfo.setAdminState(ifState.getAdminStatus() == AdminStatus.Up ? InterfaceAdminState.ENABLED : InterfaceAdminState.DISABLED);
290         interfaceInfo.setInterfaceName(interfaceName);
291         interfaceInfo.setInterfaceTag(lportTag);
292         interfaceInfo.setInterfaceType(interfaceType);
293         interfaceInfo.setGroupId(IfmUtil.getGroupId(lportTag, interfaceType));
294         interfaceInfo.setOpState(opState);
295         PhysAddress phyAddress = ifState.getPhysAddress();
296         if (phyAddress != null) {
297             interfaceInfo.setMacAddress(ifState.getPhysAddress().getValue());
298         }
299
300         return interfaceInfo;
301     }
302
303     @Override
304     public InterfaceInfo getInterfaceInfoFromOperationalDataStore(String interfaceName) {
305         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
306             ifState = InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName, dataBroker);
307         if (ifState == null) {
308             LOG.error("Interface {} is not present", interfaceName);
309             return null;
310         }
311
312         return populateInterfaceInfo(interfaceName, ifState);
313     }
314
315
316     public InterfaceInfo populateInterfaceInfo(String interfaceName, org.opendaylight.yang.gen.v1.urn.ietf.params.xml
317         .ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
318         Integer lportTag = ifState.getIfIndex();
319         InterfaceInfo interfaceInfo = new InterfaceInfo(interfaceName);
320         NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(ifState);
321         if (ncId != null) {
322             if (Tunnel.class.equals(ifState.getType())) {
323                 interfaceInfo.setPortName(interfaceName);
324             } else {
325                 Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
326                 ParentRefs parentRefs = iface.getAugmentation(ParentRefs.class);
327                 interfaceInfo.setPortName(parentRefs.getParentInterface());
328             }
329             interfaceInfo.setDpId(IfmUtil.getDpnFromNodeConnectorId(ncId));
330             interfaceInfo.setPortNo(Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId)));
331         }
332         InterfaceInfo.InterfaceOpState opState ;
333         if (ifState.getOperStatus() == OperStatus.Up) {
334             opState = InterfaceInfo.InterfaceOpState.UP;
335         } else if (ifState.getOperStatus() == OperStatus.Down) {
336             opState = InterfaceInfo.InterfaceOpState.DOWN;
337         } else {
338             opState = InterfaceInfo.InterfaceOpState.UNKNOWN;
339         }
340         interfaceInfo.setAdminState((ifState.getAdminStatus() == AdminStatus.Up) ? InterfaceAdminState.ENABLED
341             : InterfaceAdminState.DISABLED);
342         interfaceInfo.setInterfaceName(interfaceName);
343         if (lportTag != null) {
344             interfaceInfo.setInterfaceTag(lportTag);
345         }
346         interfaceInfo.setOpState(opState);
347         PhysAddress phyAddress = ifState.getPhysAddress();
348         if (phyAddress != null) {
349             interfaceInfo.setMacAddress(ifState.getPhysAddress().getValue());
350         }
351         return interfaceInfo;
352     }
353
354
355     @Override
356     public InterfaceInfo getInterfaceInfoFromOperationalDSCache(String interfaceName) {
357         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
358             ifState = InterfaceManagerCommonUtils.getInterfaceStateFromCache(interfaceName);
359         if (ifState == null) {
360             LOG.warn("Interface {} is not present", interfaceName);
361             return null;
362         }
363         return populateInterfaceInfo(interfaceName, ifState);
364     }
365
366     @Override
367     public Interface getInterfaceInfoFromConfigDataStore(String interfaceName) {
368         Interface intf = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName), dataBroker);
369         return intf;
370     }
371
372     @Override
373     public void createVLANInterface(String interfaceName, String portName, BigInteger dpId, Integer vlanId,
374                                     String description, IfL2vlan.L2vlanMode l2vlanMode) throws InterfaceAlreadyExistsException {
375         createVLANInterface(interfaceName, portName, dpId, vlanId, description, l2vlanMode, false);
376     }
377     @Override
378     public void createVLANInterface(String interfaceName, String portName, BigInteger dpId, Integer vlanId,
379                                     String description, IfL2vlan.L2vlanMode l2vlanMode, boolean isExternal) throws InterfaceAlreadyExistsException {
380
381         LOG.info("Create VLAN interface : {}", interfaceName);
382         InstanceIdentifier<Interface> interfaceInstanceIdentifier = InterfaceManagerCommonUtils.getInterfaceIdentifier(new InterfaceKey(interfaceName));
383         Interface interfaceOptional = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName), dataBroker);
384         if (interfaceOptional != null) {
385             LOG.debug("VLAN interface is already exist", interfaceOptional.getDescription());
386             throw new InterfaceAlreadyExistsException(interfaceOptional.getName());
387         }
388         IfL2vlanBuilder l2vlanBuilder = new IfL2vlanBuilder().setL2vlanMode(l2vlanMode);
389         if (vlanId != null && vlanId > 0) {
390             l2vlanBuilder.setVlanId(new VlanId(vlanId));
391         }
392         ParentRefs parentRefs = new ParentRefsBuilder().setParentInterface(portName).build();
393         InterfaceBuilder interfaceBuilder = new InterfaceBuilder().setEnabled(true).setName(interfaceName).setType(L2vlan.class).
394                 addAugmentation(IfL2vlan.class, l2vlanBuilder.build()).addAugmentation(ParentRefs.class, parentRefs).
395                 setDescription(description);
396         if (isExternal) {
397             interfaceBuilder.addAugmentation(IfExternal.class, new IfExternalBuilder().setExternal(true).build());
398         }
399         WriteTransaction t = dataBroker.newWriteOnlyTransaction();
400         t.put(LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier, interfaceBuilder.build(), true);
401         t.submit();
402     }
403
404     private boolean isServiceBoundOnInterface(short servicePriority, String interfaceName,
405                                               Class<? extends ServiceModeBase> serviceMode) {
406         InstanceIdentifier<BoundServices> boundServicesIId =
407             IfmUtil.buildBoundServicesIId(servicePriority, interfaceName, serviceMode);
408         try {
409             return SingleTransactionDataBroker.syncReadOptional(dataBroker,
410                                                                 LogicalDatastoreType.CONFIGURATION, boundServicesIId)
411                                               .isPresent();
412         } catch (ReadFailedException e) {
413             LOG.warn("Error while reading [{}]", boundServicesIId, e);
414             return false;
415         }
416     }
417
418     @Override
419     public boolean isServiceBoundOnInterfaceForIngress(short servicePriority, String interfaceName) {
420         return isServiceBoundOnInterface(servicePriority, interfaceName, ServiceModeIngress.class);
421     }
422
423     @Override
424     public boolean isServiceBoundOnInterfaceForEgress(short servicePriority, String interfaceName) {
425         return isServiceBoundOnInterface(servicePriority, interfaceName, ServiceModeEgress.class);
426     }
427
428     @Override
429     public void bindService(String interfaceName, Class<? extends ServiceModeBase> serviceMode,
430                             BoundServices serviceInfo) {
431         bindService(interfaceName, serviceMode, serviceInfo, /*WriteTransaction*/ null);
432     }
433
434     @Override
435     public void bindService(String interfaceName, Class<? extends ServiceModeBase> serviceMode,
436                             BoundServices serviceInfo, WriteTransaction tx) {
437         WriteTransaction t = (tx != null) ? tx : dataBroker.newWriteOnlyTransaction();
438         IfmUtil.bindService(t, interfaceName, serviceInfo, serviceMode);
439         if (tx == null) {
440             t.submit();
441         }
442     }
443
444     @Override
445     public void unbindService(String interfaceName, Class<? extends ServiceModeBase> serviceMode, BoundServices serviceInfo) {
446         IfmUtil.unbindService(dataBroker, interfaceName,
447                 FlowBasedServicesUtils.buildServiceId(interfaceName, serviceInfo.getServicePriority(), serviceMode));
448     }
449
450     @Override
451     public BigInteger getDpnForInterface(String ifName) {
452         GetDpidFromInterfaceInput input = new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
453         Future<RpcResult<GetDpidFromInterfaceOutput>> output = interfaceManagerRpcService.getDpidFromInterface(input);
454         try {
455             RpcResult<GetDpidFromInterfaceOutput> dpn = output.get();
456             if (dpn.isSuccessful()) {
457                 return dpn.getResult().getDpid();
458             }
459         } catch (NullPointerException | InterruptedException | ExecutionException e) {
460             LOG.warn("Exception when getting port for interface", e);
461         }
462         return null;
463     }
464
465     @Override
466     public String getEndpointIpForDpn(BigInteger dpnId) {
467         GetEndpointIpForDpnInput input = new GetEndpointIpForDpnInputBuilder().setDpid(dpnId).build();
468         Future<RpcResult<GetEndpointIpForDpnOutput>> output = interfaceManagerRpcService.getEndpointIpForDpn(input);
469         try {
470             RpcResult<GetEndpointIpForDpnOutput> ipForDpnOutputRpcResult = output.get();
471             if (ipForDpnOutputRpcResult.isSuccessful()) {
472                 List<IpAddress> localIps = ipForDpnOutputRpcResult.getResult().getLocalIps();
473                 if (!localIps.isEmpty()) {
474                     return localIps.get(0).getIpv4Address().getValue();
475                 }
476             }
477         } catch (NullPointerException | InterruptedException | ExecutionException e) {
478             LOG.warn("Exception when getting port for interface", e);
479         }
480         return null;
481     }
482
483     @Override
484     public List<ActionInfo> getInterfaceEgressActions(String ifName) {
485         return IfmUtil.getEgressActionInfosForInterface(ifName, 0, dataBroker, false);
486     }
487
488     @Override
489     public BigInteger getDpnForInterface(Interface intrf) {
490         return getDpnForInterface(intrf.getName());
491     }
492
493     @Override
494     public List<Interface> getVlanInterfaces() {
495         return InterfaceManagerCommonUtils.getAllVlanInterfacesFromCache();
496     }
497
498     @Override
499     public List<Interface> getVxlanInterfaces() {
500         return InterfaceManagerCommonUtils.getAllTunnelInterfacesFromCache();
501     }
502
503     @Override
504     public boolean isExternalInterface(String interfaceName) {
505         return isExternalInterface(getInterfaceInfoFromConfigDataStore(interfaceName));
506     }
507
508     private boolean isExternalInterface(Interface iface) {
509         if (iface == null) {
510             return false;
511         }
512
513         IfExternal ifExternal = iface.getAugmentation(IfExternal.class);
514         return ifExternal != null && Boolean.TRUE.equals(ifExternal.isExternal());
515     }
516
517     @Override
518     public String getPortNameForInterface(NodeConnectorId nodeConnectorId, String interfaceName) {
519         return InterfaceManagerCommonUtils.getPortNameForInterface(nodeConnectorId, interfaceName);
520     }
521
522     @Override
523     public String getPortNameForInterface(String dpnId, String interfaceName) {
524         return InterfaceManagerCommonUtils.getPortNameForInterface(dpnId, interfaceName);
525     }
526
527     @Override
528     public String getParentRefNameForInterface(String interfaceName) {
529         String parentRefName = null;
530
531         // FIXME Note this utility isn't very good for scale/performance as it traverses all nodes,
532         // probably need to use a cache instead of these (iface_name->dpnId+tpName).
533         Node node = southboundUtils.getNodeByTerminationPointExternalId(interfaceName);
534         if (node != null) {
535             String dpnId = southboundUtils.getDataPathIdStr(node);
536             if (dpnId == null) {
537                 LOG.error("Got node {} when looking for TP with external ID {}, "
538                         + "but unexpectedly got NULL dpnId for this node", node, interfaceName);
539                 return null;
540             }
541             TerminationPoint tp = SouthboundUtils.getTerminationPointByExternalId(node, interfaceName);
542             if (tp == null) {
543                 LOG.error("Got node {} when looking for TP with external ID {}, "
544                         + "but unexpectedly got a NULL TP from this node", node, interfaceName);
545                 return null;
546             }
547             OvsdbTerminationPointAugmentation ovsdbTp = tp.getAugmentation(OvsdbTerminationPointAugmentation.class);
548             parentRefName = getPortNameForInterface(dpnId, ovsdbTp.getName());
549             LOG.debug("Building parent ref for neutron port {}, using parentRefName {} acquired by external ID",
550                     interfaceName, parentRefName);
551         } else {
552             LOG.debug("Skipping parent ref for neutron port {}, as there is no termination point that references "
553                     + "this neutron port yet.", interfaceName);
554         }
555
556         return parentRefName;
557     }
558
559     @Override
560     public void updateInterfaceParentRef(String interfaceName, String parentInterface) {
561         // This should generally be called by EOS Owner for INTERFACE_CONFIG_ENTITY - runOnlyInLeaderNode()
562         updateInterfaceParentRef(interfaceName, parentInterface, true);
563     }
564
565     @Override
566     public void updateInterfaceParentRef(String interfaceName, String parentInterface, boolean readInterfaceBeforeWrite) {
567         // This should generally be called by EOS Owner for INTERFACE_CONFIG_ENTITY - runOnlyInLeaderNode()
568         if (interfaceName == null) {
569             return;
570         }
571
572         DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
573         ParentRefUpdateWorker parentRefUpdateWorker =
574                 new ParentRefUpdateWorker(interfaceName, parentInterface, readInterfaceBeforeWrite);
575         jobCoordinator.enqueueJob(interfaceName, parentRefUpdateWorker, IfmConstants.JOB_MAX_RETRIES);
576     }
577
578     public class ParentRefUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
579         String interfaceName;
580         String parentInterfaceName;
581         Boolean readInterfaceBeforeWrite;
582
583         public ParentRefUpdateWorker(String interfaceName, String parentInterfaceName, boolean readInterfaceBeforeWrite) {
584             this.interfaceName = interfaceName;
585             this.parentInterfaceName = parentInterfaceName;
586             this.readInterfaceBeforeWrite = readInterfaceBeforeWrite;
587         }
588
589         @Override
590         public List<ListenableFuture<Void>> call() throws Exception {
591             if (readInterfaceBeforeWrite) {
592                 Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
593                 if (iface == null) {
594                     LOG.debug("Interface doesn't exist in config DS - no need to update parentRef, skipping");
595                     return null;
596                 }
597             }
598             WriteTransaction t = dataBroker.newWriteOnlyTransaction();
599             IfmUtil.updateInterfaceParentRef(t, interfaceName, parentInterfaceName);
600             CheckedFuture<Void, TransactionCommitFailedException> submitFuture = t.submit();
601             List<ListenableFuture<Void>> futures = new ArrayList<>();
602             futures.add(submitFuture);
603             return futures;
604         }
605     }
606
607 }