BUG:5042 LLDP Tunnel Monitoring should update the interface operational
[vpnservice.git] / interfacemgr / interfacemgr-impl / src / main / java / org / opendaylight / vpnservice / interfacemgr / commons / AlivenessMonitorUtils.java
1 /*
2  * Copyright (c) 2015 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.vpnservice.interfacemgr.commons;
9
10 import com.google.common.base.Optional;
11 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
12 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
13 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
14 import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
15 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
16 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.*;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.IpAddress;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.params.SourceBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.create.input.ProfileBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.start.input.ConfigBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.*;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterface;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterfaceBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterfaceKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorId;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorIdBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorIdKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntry;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterface;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterfaceBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterfaceKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.opendaylight.yangtools.yang.common.RpcResult;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 import java.util.ArrayList;
55 import java.util.List;
56 import java.util.concurrent.ExecutionException;
57 import java.util.concurrent.Future;
58
59 public class AlivenessMonitorUtils {
60
61     private static final Logger LOG = LoggerFactory.getLogger(AlivenessMonitorUtils.class);
62     private static final int FAILURE_THRESHOLD = 4;
63     private static final int MONITORING_INTERVAL = 10;
64     private static final int MONITORING_WINDOW = 4;
65
66     public static void startLLDPMonitoring(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
67                                             Interface trunkInterface) {
68         //LLDP monitoring for the trunk interface
69         /*String trunkInterfaceName = trunkInterface.getName();
70         IfTunnel ifTunnel = trunkInterface.getAugmentation(IfTunnel.class);
71         if(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
72             MonitorStartInput lldpMonitorInput = new MonitorStartInputBuilder().setConfig(new ConfigBuilder()
73                     .setSource(new SourceBuilder().setEndpointType(getInterfaceForMonitoring(trunkInterfaceName,
74                             ifTunnel.getTunnelSource())).build())
75                     .setMode(MonitoringMode.OneOne)
76                     .setProfileId(allocateProfile(alivenessMonitorService, FAILURE_THRESHOLD, MONITORING_INTERVAL, MONITORING_WINDOW,
77                             EtherTypes.Lldp)).build()).build();
78             try {
79                 Future<RpcResult<MonitorStartOutput>> result = alivenessMonitorService.monitorStart(lldpMonitorInput);
80                 RpcResult<MonitorStartOutput> rpcResult = result.get();
81                 long monitorId;
82                 if (rpcResult.isSuccessful()) {
83                     monitorId = rpcResult.getResult().getMonitorId();
84                     createOrUpdateInterfaceMonitorIdMap(dataBroker, trunkInterfaceName, monitorId);
85                     createOrUpdateMonitorIdInterfaceMap(dataBroker, trunkInterfaceName, monitorId);
86                     LOG.trace("Started LLDP monitoring with id {}", monitorId);
87                 } else {
88                     LOG.warn("RPC Call to start monitoring returned with Errors {}", rpcResult.getErrors());
89                 }
90             } catch (InterruptedException | ExecutionException e) {
91                 LOG.warn("Exception when starting monitoring", e);
92             }
93         }*/
94     }
95
96     public static void stopLLDPMonitoring(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
97                                           Interface trunkInterface) {
98         /*IfTunnel ifTunnel = trunkInterface.getAugmentation(IfTunnel.class);
99         if(!ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)){
100             return;
101         }
102         List<Long> monitorIds = getMonitorIdForInterface(dataBroker, trunkInterface.getName());
103         if (monitorIds == null) {
104             LOG.error("Monitor Id doesn't exist for Interface {}", trunkInterface);
105             return;
106         }
107         for (Long monitorId : monitorIds) {
108             String interfaceName = getInterfaceFromMonitorId(dataBroker, monitorId);
109             if (interfaceName != null) {
110                 MonitorStopInput input = new MonitorStopInputBuilder().setMonitorId(monitorId).build();
111                 alivenessMonitorService.monitorStop(input);
112                 removeMonitorIdInterfaceMap(dataBroker, monitorId);
113                 removeMonitorIdFromInterfaceMonitorIdMap(dataBroker, interfaceName, monitorId);
114                 return;
115             }
116         }*/
117     }
118
119     public static String getInterfaceFromMonitorId(DataBroker broker, Long monitorId) {
120         InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
121         Optional<MonitorIdInterface> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
122         if(interfaceMonitorIdMap.isPresent()) {
123             return interfaceMonitorIdMap.get().getInterfaceName();
124         }
125         return null;
126     }
127
128     private static void removeMonitorIdInterfaceMap(DataBroker broker, long monitorId) {
129         InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
130         Optional<MonitorIdInterface> monitorIdInterfaceMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
131         if(monitorIdInterfaceMap.isPresent()) {
132             MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
133         }
134     }
135
136     private static void removeMonitorIdFromInterfaceMonitorIdMap(DataBroker broker, String infName, long monitorId) {
137         InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
138         Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
139         if(interfaceMonitorIdMap.isPresent()) {
140             InterfaceMonitorId interfaceMonitorIdInstance = interfaceMonitorIdMap.get();
141             List<Long> existingMonitorIds = interfaceMonitorIdInstance.getMonitorId();
142             if (existingMonitorIds != null && existingMonitorIds.contains(monitorId)) {
143                 existingMonitorIds.remove(monitorId);
144                 InterfaceMonitorIdBuilder interfaceMonitorIdBuilder = new InterfaceMonitorIdBuilder();
145                 interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setKey(new InterfaceMonitorIdKey(infName)).setMonitorId(existingMonitorIds).build();
146                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
147             }
148         }
149     }
150
151     private static org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.Interface getInterfaceForMonitoring(String interfaceName, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress ipAddress) {
152         return new org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.
153                 endpoint.type.InterfaceBuilder().setInterfaceIp(ipAddress).setInterfaceName(interfaceName).build();
154     }
155
156     protected void handleTunnelMonitorEnabledUpdates(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
157                                                      List<String> interfaceNames, boolean origMonitorEnabled, boolean updatedMonitorEnabled) {
158         for (String interfaceName : interfaceNames) {
159             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface tunnelInterface =
160                     InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName), dataBroker);
161             IfTunnel ifTunnel = tunnelInterface.getAugmentation(IfTunnel.class);
162             InterfaceManagerCommonUtils.updateTunnelMonitorDetailsInConfigDS(dataBroker, interfaceName, updatedMonitorEnabled, 3);
163             // Check if monitoring is started already
164             if (getMonitorIdForInterface(dataBroker, interfaceName) != null) {
165                 // Get updated Interface details from Config DS
166                 if(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
167                     if (updatedMonitorEnabled) {
168                         startLLDPMonitoring(alivenessMonitorService, dataBroker, tunnelInterface);
169                     } else {
170                         stopLLDPMonitoring(alivenessMonitorService, dataBroker, tunnelInterface);
171                     }
172                 }
173             }
174         }
175     }
176
177     protected void handleTunnelMonitorIntervalUpdates(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
178                                                       List<String> interfaceNames, long origMonitorInterval, long updatedMonitorInterval) {
179         for (String interfaceName : interfaceNames) {
180             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface tunnelInterface =
181                     InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName), dataBroker);
182             IfTunnel ifTunnel = tunnelInterface.getAugmentation(IfTunnel.class);
183             InterfaceManagerCommonUtils.updateTunnelMonitorDetailsInConfigDS(dataBroker, interfaceName, ifTunnel.isMonitorEnabled(), updatedMonitorInterval);
184             // Restart LLDP monitoring only if it's started already
185             List<Long> monitorIds = getMonitorIdForInterface(dataBroker, interfaceName);
186             if (monitorIds != null && monitorIds.size() > 1) {
187                 // Get updated Interface details from Config DS
188                 if(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
189                     stopLLDPMonitoring(alivenessMonitorService, dataBroker, tunnelInterface);
190                     startLLDPMonitoring(alivenessMonitorService, dataBroker,tunnelInterface);
191                 }
192             }
193         }
194         // Delete old profile from Aliveness Manager
195         if (origMonitorInterval > 0) {
196             long profileId = allocateProfile(alivenessMonitorService, 4, origMonitorInterval, 4, EtherTypes.Lldp);
197             MonitorProfileDeleteInput  profileDeleteInput = new MonitorProfileDeleteInputBuilder().setProfileId(profileId).build();
198             alivenessMonitorService.monitorProfileDelete(profileDeleteInput);
199         }
200     }
201
202
203     public static void createOrUpdateInterfaceMonitorIdMap(DataBroker broker, String infName, long monitorId) {
204         InterfaceMonitorId interfaceMonitorIdInstance;
205         List<Long> existingMonitorIds;
206         InterfaceMonitorIdBuilder interfaceMonitorIdBuilder = new InterfaceMonitorIdBuilder();
207         InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
208         Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
209         if (interfaceMonitorIdMap.isPresent()) {
210             interfaceMonitorIdInstance = interfaceMonitorIdMap.get();
211             existingMonitorIds = interfaceMonitorIdInstance.getMonitorId();
212             if (existingMonitorIds == null) {
213                 existingMonitorIds = new ArrayList<>();
214             }
215             if (!existingMonitorIds.contains(monitorId)) {
216                 existingMonitorIds.add(monitorId);
217                 interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setKey(new InterfaceMonitorIdKey(infName)).setMonitorId(existingMonitorIds).build();
218                 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
219             }
220         } else {
221             existingMonitorIds = new ArrayList<>();
222             existingMonitorIds.add(monitorId);
223             interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setMonitorId(existingMonitorIds).setKey(new InterfaceMonitorIdKey(infName)).setInterfaceName(infName).build();
224             MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
225         }
226     }
227
228     public static void createOrUpdateMonitorIdInterfaceMap(DataBroker broker,String infName,  long monitorId) {
229         MonitorIdInterface monitorIdInterfaceInstance;
230         String existinginterfaceName;
231         MonitorIdInterfaceBuilder monitorIdInterfaceBuilder = new MonitorIdInterfaceBuilder();
232         InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
233         Optional<MonitorIdInterface> monitorIdInterfaceMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
234         if(monitorIdInterfaceMap.isPresent()) {
235             monitorIdInterfaceInstance = monitorIdInterfaceMap.get();
236             existinginterfaceName = monitorIdInterfaceInstance.getInterfaceName();
237             if(!existinginterfaceName.equals(infName)) {
238                 monitorIdInterfaceInstance = monitorIdInterfaceBuilder.setKey(new MonitorIdInterfaceKey(monitorId)).setInterfaceName(infName).build();
239                 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, monitorIdInterfaceInstance);
240             }
241         } else {
242             monitorIdInterfaceInstance = monitorIdInterfaceBuilder.setMonitorId(monitorId).setKey(new MonitorIdInterfaceKey(monitorId)).setInterfaceName(infName).build();
243             MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, monitorIdInterfaceInstance);
244         }
245     }
246
247     public static List<Long> getMonitorIdForInterface(DataBroker broker, String infName) {
248         InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
249         Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
250         if(interfaceMonitorIdMap.isPresent()) {
251             return interfaceMonitorIdMap.get().getMonitorId();
252         }
253         return null;
254     }
255
256     public static long allocateProfile(AlivenessMonitorService alivenessMonitor, long failureThreshold, long interval, long window, EtherTypes etherType ) {
257         MonitorProfileCreateInput input = new MonitorProfileCreateInputBuilder().setProfile(new ProfileBuilder().setFailureThreshold(failureThreshold)
258                 .setMonitorInterval(interval).setMonitorWindow(window).setProtocolType(etherType).build()).build();
259         try {
260             Future<RpcResult<MonitorProfileCreateOutput>> result = alivenessMonitor.monitorProfileCreate(input);
261             RpcResult<MonitorProfileCreateOutput> rpcResult = result.get();
262             if(rpcResult.isSuccessful()) {
263                 return rpcResult.getResult().getProfileId();
264             } else {
265                 LOG.warn("RPC Call to Get Profile Id Id returned with Errors {}", rpcResult.getErrors());
266             }
267         } catch (InterruptedException | ExecutionException e) {
268             LOG.warn("Exception when allocating profile Id",e);
269         }
270         return 0;
271     }
272 }