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