CLI to display Of-Port status
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / impl / ItmProvider.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.itm.impl;
9
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.util.Collection;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Optional;
16 import java.util.concurrent.ExecutionException;
17 import java.util.regex.Matcher;
18 import java.util.regex.Pattern;
19 import javax.annotation.PostConstruct;
20 import javax.annotation.PreDestroy;
21 import javax.inject.Inject;
22 import javax.inject.Singleton;
23 import org.apache.aries.blueprint.annotation.service.Service;
24 import org.opendaylight.genius.itm.api.IITMProvider;
25 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
26 import org.opendaylight.genius.itm.cache.TunnelStateCache;
27 import org.opendaylight.genius.itm.cli.TepCommandHelper;
28 import org.opendaylight.genius.itm.cli.TepException;
29 import org.opendaylight.genius.itm.diagstatus.ItmDiagStatusProvider;
30 import org.opendaylight.genius.itm.globals.ITMConstants;
31 import org.opendaylight.genius.itm.listeners.InterfaceStateListener;
32 import org.opendaylight.genius.itm.listeners.OvsdbNodeListener;
33 import org.opendaylight.genius.itm.listeners.TransportZoneListener;
34 import org.opendaylight.genius.itm.listeners.TunnelMonitorChangeListener;
35 import org.opendaylight.genius.itm.listeners.TunnelMonitorIntervalListener;
36 import org.opendaylight.genius.itm.monitoring.ItmTunnelEventListener;
37 import org.opendaylight.genius.itm.recovery.impl.EosChangeEventHandler;
38 import org.opendaylight.genius.itm.rpc.ItmManagerRpcService;
39 import org.opendaylight.infrautils.diagstatus.ServiceState;
40 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
41 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
42 import org.opendaylight.mdsal.binding.api.DataBroker;
43 import org.opendaylight.mdsal.binding.api.RpcProviderService;
44 import org.opendaylight.mdsal.common.api.ReadFailedException;
45 import org.opendaylight.mdsal.eos.binding.api.Entity;
46 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipCandidateRegistration;
47 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipChange;
48 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipListener;
49 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipListenerRegistration;
50 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
51 import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException;
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.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.of.teps.state.OfTep;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInputBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInputBuilder;
66 import org.opendaylight.yangtools.yang.common.RpcResult;
67 import org.opendaylight.yangtools.yang.common.Uint32;
68 import org.opendaylight.yangtools.yang.common.Uint64;
69 import org.slf4j.Logger;
70 import org.slf4j.LoggerFactory;
71
72 @Singleton
73 @Service
74 public class ItmProvider implements AutoCloseable, IITMProvider /*,ItmStateService */ {
75
76     private static final Logger LOG = LoggerFactory.getLogger(ItmProvider.class);
77     private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
78
79     private final DataBroker dataBroker;
80     private final ItmManagerRpcService itmRpcService ;
81     private final IdManagerService idManager;
82     private final TepCommandHelper tepCommandHelper;
83     private final TransportZoneListener tzChangeListener;
84     private final TunnelMonitorChangeListener tnlToggleListener;
85     private final TunnelMonitorIntervalListener tnlIntervalListener;
86     private final InterfaceStateListener ifStateListener;
87     private final EntityOwnershipService entityOwnershipService;
88     private final ItmDiagStatusProvider itmStatusProvider;
89     private RpcProviderService rpcProviderService;
90     private final ItmTunnelEventListener itmStateListener;
91     private final OvsdbNodeListener ovsdbChangeListener;
92     static short flag = 0;
93     private final TunnelMonitoringConfig tunnelMonitoringConfig;
94     private EntityOwnershipCandidateRegistration registryCandidate;
95     private final DpnTepStateCache dpnTepStateCache;
96     private final TunnelStateCache tunnelStateCache;
97     private final ItmConfig itmConfig;
98     private final JobCoordinator jobCoordinator;
99     private final ItmProvider.ItmProviderEOSListener itmProviderEOSListener;
100     public  Integer batchSize;
101     public  Integer batchInterval;
102     private EosChangeEventHandler eosChangeEventHandler;
103
104     @Inject
105     public ItmProvider(DataBroker dataBroker,
106                        IdManagerService idManagerService,
107                        InterfaceStateListener interfaceStateListener,
108                        ItmManagerRpcService itmManagerRpcService,
109                        ItmTunnelEventListener itmTunnelEventListener,
110                        TepCommandHelper tepCommandHelper,
111                        TunnelMonitorChangeListener tunnelMonitorChangeListener,
112                        TunnelMonitorIntervalListener tunnelMonitorIntervalListener,
113                        TransportZoneListener transportZoneListener,
114                        OvsdbNodeListener ovsdbNodeListener,
115                        TunnelMonitoringConfig tunnelMonitoringConfig,
116                        EntityOwnershipService entityOwnershipService,
117                        DpnTepStateCache dpnTepStateCache,
118                        final ItmDiagStatusProvider itmDiagStatusProvider,
119                        final TunnelStateCache tunnelStateCache,
120                        final ItmConfig itmConfig,
121                        final JobCoordinator jobCoordinator,
122                        final EosChangeEventHandler eosChangeEventHandler) {
123         LOG.info("ItmProvider Before register MBean");
124         this.dataBroker = dataBroker;
125         this.idManager = idManagerService;
126         this.ifStateListener = interfaceStateListener;
127         this.itmRpcService = itmManagerRpcService;
128         this.itmStateListener = itmTunnelEventListener;
129         this.tepCommandHelper = tepCommandHelper;
130         this.tnlToggleListener = tunnelMonitorChangeListener;
131         this.tnlIntervalListener = tunnelMonitorIntervalListener;
132         this.tzChangeListener = transportZoneListener;
133         this.ovsdbChangeListener = ovsdbNodeListener;
134         this.tunnelMonitoringConfig = tunnelMonitoringConfig;
135         this.entityOwnershipService = entityOwnershipService;
136         this.dpnTepStateCache = dpnTepStateCache;
137         this.itmStatusProvider = itmDiagStatusProvider;
138         this.tunnelStateCache = tunnelStateCache;
139         this.eosChangeEventHandler = eosChangeEventHandler;
140
141         this.itmConfig = itmConfig;
142         this.jobCoordinator = jobCoordinator;
143         this.itmProviderEOSListener = new ItmProvider.ItmProviderEOSListener(this, this.entityOwnershipService);
144     }
145
146     @PostConstruct
147     @SuppressWarnings("checkstyle:IllegalCatch")
148     public void start() {
149         try {
150             createIdPool();
151             registerEntityForOwnership();
152             initialiseBatchingManager();
153             LOG.info("ItmProvider Started");
154         } catch (Exception ex) {
155             itmStatusProvider.reportStatus(ex);
156             LOG.info("ItmProvider failed to start", ex);
157             return;
158         }
159     }
160
161     public void initialiseBatchingManager() {
162         batchSize = ITMConstants.BATCH_SIZE;
163         LOG.info("entered initialse");
164         if (itmConfig.getBatchSize() != null) {
165             batchSize = itmConfig.getBatchSize().toJava();
166         }
167         batchInterval = ITMConstants.PERIODICITY;
168         if (itmConfig.getBatchInterval() != null) {
169             batchInterval = itmConfig.getBatchInterval().toJava();
170         }
171         ITMBatchingUtils.registerWithBatchManager(this.dataBroker,this.batchSize,this.batchInterval);
172     }
173
174     public void createDefaultTransportZone(ItmConfig itmConfigObj) {
175         jobCoordinator.enqueueJob(ITMConstants.DEFAULT_TRANSPORT_ZONE, () -> {
176             boolean defTzEnabled = itmConfigObj.isDefTzEnabled();
177             if (defTzEnabled) {
178                 String tunnelType = itmConfigObj.getDefTzTunnelType();
179                 if (tunnelType == null || tunnelType.isEmpty()) {
180                     tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN;
181                 }
182                 // validate tunnel-type and based on tunnel-type,
183                 // create default-TZ or update default-TZ if tunnel-type is changed during ODL restart
184                 configureTunnelType(ITMConstants.DEFAULT_TRANSPORT_ZONE, tunnelType);
185                 LOG.info("{} is created with {} tunnel-type.", ITMConstants.DEFAULT_TRANSPORT_ZONE, tunnelType);
186             } else {
187                 LOG.info("Removing {} on start-up, def-tz-enabled is false.", ITMConstants.DEFAULT_TRANSPORT_ZONE);
188                 // check if default-TZ already exists, then delete it because flag is OFF now.
189                 ItmUtils.deleteTransportZoneFromConfigDS(ITMConstants.DEFAULT_TRANSPORT_ZONE, dataBroker);
190             }
191             return Collections.emptyList();
192         });
193     }
194
195     private void registerEntityForOwnership() {
196         try {
197             this.registryCandidate = entityOwnershipService
198                     .registerCandidate(new Entity(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY));
199         } catch (CandidateAlreadyRegisteredException e) {
200             LOG.error("failed to register entity {} for entity-ownership-service", e.getEntity());
201         }
202     }
203
204     @Override
205     @PreDestroy
206     public void close() {
207         if (tzChangeListener != null) {
208             tzChangeListener.close();
209         }
210         if (tnlIntervalListener != null) {
211             tnlIntervalListener.close();
212         }
213         if (tnlToggleListener != null) {
214             tnlToggleListener.close();
215         }
216         if (ovsdbChangeListener != null) {
217             ovsdbChangeListener.close();
218         }
219         if (registryCandidate != null) {
220             registryCandidate.close();
221         }
222         itmStatusProvider.reportStatus(ServiceState.UNREGISTERED);
223         this.itmProviderEOSListener.close();
224         LOG.info("ItmProvider Closed");
225     }
226
227     private void createIdPool() {
228         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
229                 .setPoolName(ITMConstants.ITM_IDPOOL_NAME)
230                 .setLow(ITMConstants.ITM_IDPOOL_START)
231                 .setHigh(Uint32.valueOf(ITMConstants.ITM_IDPOOL_SIZE))
232                 .build();
233         try {
234             ListenableFuture<RpcResult<CreateIdPoolOutput>> result = idManager.createIdPool(createPool);
235             if (result != null && result.get().isSuccessful()) {
236                 LOG.debug("Created IdPool for ITM Service");
237             }
238         } catch (InterruptedException | ExecutionException e) {
239             LOG.error("Failed to create idPool for ITM Service ", e);
240         }
241     }
242
243     @Override
244     public DataBroker getDataBroker() {
245         return dataBroker;
246     }
247
248     @Override
249     public void addExternalEndpoint(Class<? extends TunnelTypeBase> tunnelType, IpAddress dcgwIP) {
250         AddExternalTunnelEndpointInput addExternalTunnelEndpointInput =
251                 new AddExternalTunnelEndpointInputBuilder().setTunnelType(tunnelType)
252                         .setDestinationIp(dcgwIP).build();
253         LoggingFutures.addErrorLogging(itmRpcService.addExternalTunnelEndpoint(addExternalTunnelEndpointInput),
254                 LOG, "addExternalTunnelEndpoint");
255     }
256
257     @Override
258     public void remExternalEndpoint(Class<? extends TunnelTypeBase> tunnelType, IpAddress dcgwIP) {
259         RemoveExternalTunnelEndpointInput removeExternalTunnelEndpointInput =
260                 new RemoveExternalTunnelEndpointInputBuilder().setTunnelType(tunnelType)
261                         .setDestinationIp(dcgwIP).build();
262         LoggingFutures.addErrorLogging(itmRpcService.removeExternalTunnelEndpoint(removeExternalTunnelEndpointInput),
263                 LOG, "removeExternalTunnelEndpoint");
264     }
265
266     @Override
267     public void createLocalCache(Uint64 dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
268             String gatewayIp, String transportZone) {
269         if (tepCommandHelper != null) {
270             try {
271                 tepCommandHelper.createLocalCache(dpnId, ipAddress, transportZone);
272             } catch (TepException e) {
273                 LOG.error("Create Local Cache failed", e);
274             }
275         } else {
276             LOG.trace("tepCommandHelper doesnt exist");
277         }
278     }
279
280     @Override
281     public void commitTeps() {
282         tepCommandHelper.deleteOnCommit();
283         tepCommandHelper.buildTeps();
284     }
285
286     @Override
287     public List<String> showTeps() {
288         try {
289             return tepCommandHelper.showTeps(tunnelMonitoringConfig.isTunnelMonitoringEnabled(),
290                     tunnelMonitoringConfig.getMonitorInterval());
291         } catch (TepException e) {
292             LOG.error("show teps failed", e);
293             return Collections.singletonList(e.getMessage());
294         }
295     }
296
297     @Override
298     public void showState(Collection<StateTunnelList> tunnels) {
299         if (tunnels != null) {
300             try {
301                 tepCommandHelper.showState(tunnels, tunnelMonitoringConfig.isTunnelMonitoringEnabled());
302             } catch (TepException e) {
303                 LOG.error("show state failed", e);
304             }
305         } else {
306             LOG.debug("No tunnels available");
307         }
308     }
309
310     @Override
311     public void showBridges(Map dpnIdBridgeRefsMap) {
312         if (!dpnIdBridgeRefsMap.isEmpty()) {
313             tepCommandHelper.showBridges(dpnIdBridgeRefsMap);
314         } else {
315             LOG.warn("tep:show-bridges => No bridges available");
316         }
317     }
318
319     @Override
320     public void showCache(String cacheName) {
321         tepCommandHelper.showCache(cacheName);
322     }
323
324     @Override
325     public void deleteVtep(Uint64 dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
326             String gatewayIp, String transportZone) {
327         try {
328             tepCommandHelper.deleteVtep(dpnId, ipAddress, transportZone);
329         } catch (TepException e) {
330             LOG.error("Delete Vteps Failed", e);
331         }
332     }
333
334     @Override
335     public void configureTunnelType(String transportZone, String tunnelType) {
336         LOG.debug("ItmProvider: configureTunnelType {} for transportZone {}", tunnelType, transportZone);
337         try {
338             tepCommandHelper.configureTunnelType(transportZone,tunnelType);
339         } catch (ExecutionException | InterruptedException e) {
340             LOG.error("configureTunnelType {} failed for transportZone {}", tunnelType, transportZone, e);
341         }
342     }
343
344     @Override
345     public void configureTunnelMonitorParams(boolean monitorEnabled, String monitorProtocol) {
346         tepCommandHelper.configureTunnelMonitorParams(monitorEnabled, monitorProtocol);
347     }
348
349     @Override
350     public void configureTunnelMonitorInterval(int interval) {
351         tepCommandHelper.configureTunnelMonitorInterval(interval);
352     }
353
354     @Override
355     public boolean validateIP(final String ip) {
356         if (ip == null || ip.isEmpty() || "null".equals(ip) || "0.0.0.0".equals(ip)) {
357             return false;
358         }
359         final String PTRN =
360                 "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
361         Pattern pattern = Pattern.compile(PTRN);
362         Matcher matcher = pattern.matcher(ip);
363         return matcher.matches();
364     }
365
366     @Override
367     public Interface getInterface(String tunnelName) {
368         return dpnTepStateCache.getInterfaceFromCache(tunnelName);
369     }
370
371     @Override
372     public Optional<StateTunnelList> getTunnelState(String interfaceName) throws ReadFailedException {
373         return tunnelStateCache.get(tunnelStateCache.getStateTunnelListIdentifier(interfaceName));
374     }
375
376     @Override
377     public void showOfPorts(Collection<OfTep> ofTeps) {
378         if (ofTeps != null) {
379             tepCommandHelper.showOfPorts(ofTeps); }
380         else {
381             LOG.debug("No ofports available"); }
382     }
383
384     public void handleOwnershipChange(EntityOwnershipChange ownershipChange,
385                                       EntityOwnershipListenerRegistration listenerRegistration) {
386         if (ownershipChange.getState().isOwner()) {
387             LOG.info("*This* instance of provider is set as a MASTER instance");
388             EVENT_LOGGER.debug("****MASTER**** instance");
389             createDefaultTransportZone(itmConfig);
390             eosChangeEventHandler.recoverUnknownTunnelsOnEosSwitch();
391         } else {
392             LOG.info("*This* instance of provider is set as a SLAVE instance");
393             EVENT_LOGGER.debug("****SLAVE**** instance");
394         }
395         itmStatusProvider.reportStatus(ServiceState.OPERATIONAL);
396     }
397
398     private static class ItmProviderEOSListener implements EntityOwnershipListener {
399         private final ItmProvider itmProviderObj;
400         private final EntityOwnershipListenerRegistration listenerRegistration;
401
402         ItmProviderEOSListener(ItmProvider itmProviderObj, EntityOwnershipService entityOwnershipService) {
403             this.itmProviderObj = itmProviderObj;
404             this.listenerRegistration = entityOwnershipService.registerListener(ITMConstants.ITM_CONFIG_ENTITY, this);
405             EVENT_LOGGER.debug("ItmProviderEOSListener: registered");
406         }
407
408         public void close() {
409             listenerRegistration.close();
410         }
411
412         @Override
413         public void ownershipChanged(EntityOwnershipChange ownershipChange) {
414             EVENT_LOGGER.debug("****ownershipChanged****");
415             itmProviderObj.handleOwnershipChange(ownershipChange, listenerRegistration);
416         }
417     }
418 }