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