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