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