Porting the modules from vpnservice to genius
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / commons / AlivenessMonitorUtils.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.genius.interfacemanager.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.common.api.data.LogicalDatastoreType;
13 import org.opendaylight.genius.interfacemanager.IfmUtil;
14 import org.opendaylight.genius.mdsalutil.MDSALUtil;
15 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.*;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.monitor.params.SourceBuilder;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.monitor.profile.create.input.Profile;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.monitor.profile.create.input.ProfileBuilder;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.monitor.start.input.ConfigBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.*;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.monitor.id.map.InterfaceMonitorId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.monitor.id.map.InterfaceMonitorIdBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._interface.monitor.id.map.InterfaceMonitorIdKey;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.monitor.id._interface.map.MonitorIdInterface;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.monitor.id._interface.map.MonitorIdInterfaceBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.monitor.id._interface.map.MonitorIdInterfaceKey;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 import org.opendaylight.yangtools.yang.common.RpcResult;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.concurrent.ExecutionException;
38 import java.util.concurrent.Future;
39
40 public class AlivenessMonitorUtils {
41
42     private static final Logger LOG = LoggerFactory.getLogger(AlivenessMonitorUtils.class);
43     private static final long FAILURE_THRESHOLD = 4;
44     private static final long MONITORING_INTERVAL = 10000;
45     private static final long MONITORING_WINDOW = 4;
46
47     public static void startLLDPMonitoring(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
48                                             Interface trunkInterface) {
49         //LLDP monitoring for the trunk interface
50         String trunkInterfaceName = trunkInterface.getName();
51         IfTunnel ifTunnel = trunkInterface.getAugmentation(IfTunnel.class);
52         if(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class) && ifTunnel.isInternal()) {
53         MonitorStartInput lldpMonitorInput = new MonitorStartInputBuilder().setConfig(new ConfigBuilder()
54              .setSource(new SourceBuilder().setEndpointType(getInterfaceForMonitoring(trunkInterfaceName,
55                      ifTunnel.getTunnelSource())).build())
56              .setMode(MonitoringMode.OneOne)
57              .setProfileId(allocateProfile(alivenessMonitorService, FAILURE_THRESHOLD, ifTunnel.getMonitorInterval(), MONITORING_WINDOW,
58                      EtherTypes.Lldp)).build()).build();
59             try {
60                 Future<RpcResult<MonitorStartOutput>> result = alivenessMonitorService.monitorStart(lldpMonitorInput);
61                 RpcResult<MonitorStartOutput> rpcResult = result.get();
62                 long monitorId;
63                 if (rpcResult.isSuccessful()) {
64                     monitorId = rpcResult.getResult().getMonitorId();
65                     createOrUpdateInterfaceMonitorIdMap(dataBroker, trunkInterfaceName, monitorId);
66                     createOrUpdateMonitorIdInterfaceMap(dataBroker, trunkInterfaceName, monitorId);
67                     LOG.trace("Started LLDP monitoring with id {}", monitorId);
68                 } else {
69                     LOG.warn("RPC Call to start monitoring returned with Errors {}", rpcResult.getErrors());
70                 }
71             } catch (InterruptedException | ExecutionException e) {
72                 LOG.warn("Exception when starting monitoring", e);
73             }
74         }
75     }
76
77     public static void stopLLDPMonitoring(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
78                                           Interface trunkInterface) {
79         IfTunnel ifTunnel = trunkInterface.getAugmentation(IfTunnel.class);
80         if(!(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)&& ifTunnel.isInternal())){
81             return;
82         }
83         List<Long> monitorIds = getMonitorIdForInterface(dataBroker, trunkInterface.getName());
84         if (monitorIds == null) {
85             LOG.error("Monitor Id doesn't exist for Interface {}", trunkInterface);
86             return;
87         }
88         for (Long monitorId : monitorIds) {
89             String interfaceName = getInterfaceFromMonitorId(dataBroker, monitorId);
90             if (interfaceName != null) {
91                 MonitorStopInput input = new MonitorStopInputBuilder().setMonitorId(monitorId).build();
92                 alivenessMonitorService.monitorStop(input);
93                 removeMonitorIdInterfaceMap(dataBroker, monitorId);
94                 removeMonitorIdFromInterfaceMonitorIdMap(dataBroker, interfaceName, monitorId);
95                 return;
96             }
97         }
98     }
99
100     public static String getInterfaceFromMonitorId(DataBroker broker, Long monitorId) {
101         InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
102         Optional<MonitorIdInterface> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
103         if(interfaceMonitorIdMap.isPresent()) {
104             return interfaceMonitorIdMap.get().getInterfaceName();
105         }
106         return null;
107     }
108
109     private static void removeMonitorIdInterfaceMap(DataBroker broker, long monitorId) {
110         InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
111         Optional<MonitorIdInterface> monitorIdInterfaceMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
112         if(monitorIdInterfaceMap.isPresent()) {
113             MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
114         }
115     }
116
117     private static void removeMonitorIdFromInterfaceMonitorIdMap(DataBroker broker, String infName, long monitorId) {
118         InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
119         Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
120         if(interfaceMonitorIdMap.isPresent()) {
121             InterfaceMonitorId interfaceMonitorIdInstance = interfaceMonitorIdMap.get();
122             List<Long> existingMonitorIds = interfaceMonitorIdInstance.getMonitorId();
123             if (existingMonitorIds != null && existingMonitorIds.contains(monitorId)) {
124                 existingMonitorIds.remove(monitorId);
125                 InterfaceMonitorIdBuilder interfaceMonitorIdBuilder = new InterfaceMonitorIdBuilder();
126                 interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setKey(new InterfaceMonitorIdKey(infName)).setMonitorId(existingMonitorIds).build();
127                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
128             }
129         }
130     }
131
132     private static org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.endpoint.endpoint.type.Interface getInterfaceForMonitoring(String interfaceName, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress ipAddress) {
133         return new org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.endpoint.
134                 endpoint.type.InterfaceBuilder().setInterfaceIp(ipAddress).setInterfaceName(interfaceName).build();
135     }
136
137     public static void handleTunnelMonitorUpdates(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
138                                                   Interface interfaceOld, Interface interfaceNew) {
139         String interfaceName = interfaceNew.getName();
140         IfTunnel ifTunnelNew = interfaceNew.getAugmentation(IfTunnel.class);
141         if(!(ifTunnelNew.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)&&
142                 ifTunnelNew.isInternal())){
143             return;
144         }
145         LOG.debug("handling tunnel monitoring updates for interface {}", interfaceName);
146         // Restart LLDP monitoring only if it's started already
147         List<Long> monitorIds = getMonitorIdForInterface(dataBroker, interfaceName);
148         if (monitorIds != null && !monitorIds.isEmpty()) {
149                 stopLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceOld);
150                 if(ifTunnelNew.isMonitorEnabled()) {
151                     startLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceNew);
152
153                     // Delete old profile from Aliveness Manager
154                     IfTunnel ifTunnelOld = interfaceOld.getAugmentation(IfTunnel.class);
155                     if(ifTunnelNew.getMonitorInterval() != ifTunnelOld.getMonitorInterval()) {
156                         LOG.debug("deleting older monitor profile for interface {}", interfaceName);
157                         long profileId = allocateProfile(alivenessMonitorService, FAILURE_THRESHOLD, ifTunnelOld.getMonitorInterval(), MONITORING_WINDOW, EtherTypes.Lldp);
158                         MonitorProfileDeleteInput profileDeleteInput = new MonitorProfileDeleteInputBuilder().setProfileId(profileId).build();
159                         alivenessMonitorService.monitorProfileDelete(profileDeleteInput);
160                     }
161                 }
162             }
163     }
164
165
166     public static void createOrUpdateInterfaceMonitorIdMap(DataBroker broker, String infName, long monitorId) {
167         InterfaceMonitorId interfaceMonitorIdInstance;
168         List<Long> existingMonitorIds;
169         InterfaceMonitorIdBuilder interfaceMonitorIdBuilder = new InterfaceMonitorIdBuilder();
170         InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
171         Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
172         if (interfaceMonitorIdMap.isPresent()) {
173             interfaceMonitorIdInstance = interfaceMonitorIdMap.get();
174             existingMonitorIds = interfaceMonitorIdInstance.getMonitorId();
175             if (existingMonitorIds == null) {
176                 existingMonitorIds = new ArrayList<>();
177             }
178             if (!existingMonitorIds.contains(monitorId)) {
179                 existingMonitorIds.add(monitorId);
180                 interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setKey(new InterfaceMonitorIdKey(infName)).setMonitorId(existingMonitorIds).build();
181                 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
182             }
183         } else {
184             existingMonitorIds = new ArrayList<>();
185             existingMonitorIds.add(monitorId);
186             interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setMonitorId(existingMonitorIds).setKey(new InterfaceMonitorIdKey(infName)).setInterfaceName(infName).build();
187             MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
188         }
189     }
190
191     public static void createOrUpdateMonitorIdInterfaceMap(DataBroker broker, String infName, long monitorId) {
192         MonitorIdInterface monitorIdInterfaceInstance;
193         String existinginterfaceName;
194         MonitorIdInterfaceBuilder monitorIdInterfaceBuilder = new MonitorIdInterfaceBuilder();
195         InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
196         Optional<MonitorIdInterface> monitorIdInterfaceMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
197         if(monitorIdInterfaceMap.isPresent()) {
198             monitorIdInterfaceInstance = monitorIdInterfaceMap.get();
199             existinginterfaceName = monitorIdInterfaceInstance.getInterfaceName();
200             if(!existinginterfaceName.equals(infName)) {
201                 monitorIdInterfaceInstance = monitorIdInterfaceBuilder.setKey(new MonitorIdInterfaceKey(monitorId)).setInterfaceName(infName).build();
202                 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, monitorIdInterfaceInstance);
203             }
204         } else {
205             monitorIdInterfaceInstance = monitorIdInterfaceBuilder.setMonitorId(monitorId).setKey(new MonitorIdInterfaceKey(monitorId)).setInterfaceName(infName).build();
206             MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, monitorIdInterfaceInstance);
207         }
208     }
209
210     public static List<Long> getMonitorIdForInterface(DataBroker broker, String infName) {
211         InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
212         Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
213         if(interfaceMonitorIdMap.isPresent()) {
214             return interfaceMonitorIdMap.get().getMonitorId();
215         }
216         return null;
217     }
218
219     public static long createMonitorProfile(AlivenessMonitorService alivenessMonitor, MonitorProfileCreateInput monitorProfileCreateInput) {
220         try {
221             Future<RpcResult<MonitorProfileCreateOutput>> result = alivenessMonitor.monitorProfileCreate(monitorProfileCreateInput);
222             RpcResult<MonitorProfileCreateOutput> rpcResult = result.get();
223             if(rpcResult.isSuccessful()) {
224                 return rpcResult.getResult().getProfileId();
225             } else {
226                 LOG.warn("RPC Call to Get Profile Id Id returned with Errors {}.. Trying to fetch existing profile ID", rpcResult.getErrors());
227                 try{
228                     Profile createProfile = monitorProfileCreateInput.getProfile();
229                     Future<RpcResult<MonitorProfileGetOutput>> existingProfile = alivenessMonitor.monitorProfileGet(buildMonitorGetProfile(createProfile.getMonitorInterval(), createProfile.getMonitorWindow(), createProfile.getFailureThreshold(), createProfile.getProtocolType()));
230                     RpcResult<MonitorProfileGetOutput> rpcGetResult = existingProfile.get();
231                     if(rpcGetResult.isSuccessful()){
232                         return rpcGetResult.getResult().getProfileId();
233                     }else{
234                         LOG.warn("RPC Call to Get Existing Profile Id returned with Errors {}", rpcGetResult.getErrors());
235                     }
236                 }catch(Exception e){
237                     LOG.warn("Exception when getting existing profile",e);
238                 }
239             }
240         } catch (InterruptedException | ExecutionException e) {
241             LOG.warn("Exception when allocating profile Id",e);
242         }
243         return 0;
244     }
245
246     private static MonitorProfileGetInput buildMonitorGetProfile(long monitorInterval, long monitorWindow, long failureThreshold, EtherTypes protocolType){
247         MonitorProfileGetInputBuilder buildGetProfile = new MonitorProfileGetInputBuilder();
248         org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.monitor.profile.get.input.ProfileBuilder profileBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.monitor.profile.get.input.ProfileBuilder();
249         profileBuilder.setFailureThreshold(failureThreshold);
250         profileBuilder.setMonitorInterval(monitorInterval);
251         profileBuilder.setMonitorWindow(monitorWindow);
252         profileBuilder.setProtocolType(protocolType);
253         buildGetProfile.setProfile(profileBuilder.build());
254         return (buildGetProfile.build());
255     };
256
257     public static long allocateProfile(AlivenessMonitorService alivenessMonitor, long FAILURE_THRESHOLD, long MONITORING_INTERVAL,
258                                               long MONITORING_WINDOW, EtherTypes etherTypes) {
259         MonitorProfileCreateInput input = new MonitorProfileCreateInputBuilder().
260                 setProfile(new ProfileBuilder().setFailureThreshold(FAILURE_THRESHOLD)
261                         .setMonitorInterval(MONITORING_INTERVAL).setMonitorWindow(MONITORING_WINDOW).
262                                 setProtocolType(etherTypes).build()).build();
263         return createMonitorProfile(alivenessMonitor, input);
264     }
265
266     public static long allocateDefaultProfile(AlivenessMonitorService alivenessMonitor, EtherTypes etherType ) {
267         MonitorProfileCreateInput input = new MonitorProfileCreateInputBuilder().
268                 setProfile(getDefaultMonitorProfile(etherType)).build();
269         return createMonitorProfile(alivenessMonitor, input);
270     }
271
272     public static Profile getDefaultMonitorProfile(EtherTypes etherType) {
273         ProfileBuilder profileBuilder = new ProfileBuilder();
274         profileBuilder.setProtocolType(etherType);
275         profileBuilder.setFailureThreshold(FAILURE_THRESHOLD)
276                     .setMonitorInterval(MONITORING_INTERVAL).setMonitorWindow(MONITORING_WINDOW).setProtocolType(etherType);
277         return profileBuilder.build();
278     }
279 }