Genius Neon MRI changes
[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.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.math.BigInteger;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.List;
17 import java.util.concurrent.ExecutionException;
18 import java.util.regex.Matcher;
19 import java.util.regex.Pattern;
20 import javax.annotation.PostConstruct;
21 import javax.annotation.PreDestroy;
22 import javax.inject.Inject;
23 import javax.inject.Singleton;
24
25 import org.apache.aries.blueprint.annotation.service.Service;
26 import org.apache.felix.service.command.CommandSession;
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
30 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
31 import org.opendaylight.genius.itm.api.IITMProvider;
32 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
33 import org.opendaylight.genius.itm.cache.TunnelStateCache;
34 import org.opendaylight.genius.itm.cli.TepCommandHelper;
35 import org.opendaylight.genius.itm.cli.TepException;
36 import org.opendaylight.genius.itm.diagstatus.ItmDiagStatusProvider;
37 import org.opendaylight.genius.itm.globals.ITMConstants;
38 import org.opendaylight.genius.itm.listeners.InterfaceStateListener;
39 import org.opendaylight.genius.itm.listeners.OvsdbNodeListener;
40 import org.opendaylight.genius.itm.listeners.TransportZoneListener;
41 import org.opendaylight.genius.itm.listeners.TunnelMonitorChangeListener;
42 import org.opendaylight.genius.itm.listeners.TunnelMonitorIntervalListener;
43 import org.opendaylight.genius.itm.listeners.VtepConfigSchemaListener;
44 import org.opendaylight.genius.itm.monitoring.ItmTunnelEventListener;
45 import org.opendaylight.genius.itm.rpc.ItmManagerRpcService;
46 import org.opendaylight.genius.mdsalutil.MDSALUtil;
47 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
48 import org.opendaylight.infrautils.diagstatus.ServiceState;
49 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
50 import org.opendaylight.infrautils.utils.concurrent.JdkFutures;
51 import org.opendaylight.mdsal.eos.binding.api.Entity;
52 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipCandidateRegistration;
53 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
54 import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.VtepConfigSchemas;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.vtep.config.schemas.VtepConfigSchema;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.vtep.config.schemas.VtepConfigSchemaBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInputBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInputBuilder;
71 import org.opendaylight.yangtools.yang.common.RpcResult;
72 import org.slf4j.Logger;
73 import org.slf4j.LoggerFactory;
74
75 @Singleton
76 @Service
77 public class ItmProvider implements AutoCloseable, IITMProvider /*,ItmStateService */ {
78
79     private static final Logger LOG = LoggerFactory.getLogger(ItmProvider.class);
80
81     private final DataBroker dataBroker;
82     private final ItmManagerRpcService itmRpcService ;
83     private final IdManagerService idManager;
84     private final TepCommandHelper tepCommandHelper;
85     private final TransportZoneListener tzChangeListener;
86     private final TunnelMonitorChangeListener tnlToggleListener;
87     private final TunnelMonitorIntervalListener tnlIntervalListener;
88     private final VtepConfigSchemaListener vtepConfigSchemaListener;
89     private final InterfaceStateListener ifStateListener;
90     private final EntityOwnershipService entityOwnershipService;
91     private final ItmDiagStatusProvider itmStatusProvider;
92     private RpcProviderRegistry rpcProviderRegistry;
93     private final ItmTunnelEventListener itmStateListener;
94     private final OvsdbNodeListener ovsdbChangeListener;
95     static short flag = 0;
96     private final TunnelMonitoringConfig tunnelMonitoringConfig;
97     private EntityOwnershipCandidateRegistration registryCandidate;
98     private final DpnTepStateCache dpnTepStateCache;
99     private final TunnelStateCache tunnelStateCache;
100     private final ItmConfig itmConfig;
101     private final JobCoordinator jobCoordinator;
102     private final EntityOwnershipUtils entityOwnershipUtils;
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                        VtepConfigSchemaListener vtepConfigSchemaListener,
115                        OvsdbNodeListener ovsdbNodeListener,
116                        TunnelMonitoringConfig tunnelMonitoringConfig,
117                        EntityOwnershipService entityOwnershipService,
118                        DpnTepStateCache dpnTepStateCache,
119                        final ItmDiagStatusProvider itmDiagStatusProvider,
120                        final TunnelStateCache tunnelStateCache,
121                        final ItmConfig itmConfig,
122                        final JobCoordinator jobCoordinator,
123                        final EntityOwnershipUtils entityOwnershipUtils) {
124         LOG.info("ItmProvider Before register MBean");
125         this.dataBroker = dataBroker;
126         this.idManager = idManagerService;
127         this.ifStateListener = interfaceStateListener;
128         this.itmRpcService = itmManagerRpcService;
129         this.itmStateListener = itmTunnelEventListener;
130         this.tepCommandHelper = tepCommandHelper;
131         this.tnlToggleListener = tunnelMonitorChangeListener;
132         this.tnlIntervalListener = tunnelMonitorIntervalListener;
133         this.tzChangeListener = transportZoneListener;
134         this.vtepConfigSchemaListener = vtepConfigSchemaListener;
135         this.ovsdbChangeListener = ovsdbNodeListener;
136         this.tunnelMonitoringConfig = tunnelMonitoringConfig;
137         this.entityOwnershipService = entityOwnershipService;
138         this.dpnTepStateCache = dpnTepStateCache;
139         this.itmStatusProvider = itmDiagStatusProvider;
140         this.tunnelStateCache = tunnelStateCache;
141         ITMBatchingUtils.registerWithBatchManager(this.dataBroker);
142
143         this.itmConfig = itmConfig;
144         this.jobCoordinator = jobCoordinator;
145         this.entityOwnershipUtils = entityOwnershipUtils;
146     }
147
148     @PostConstruct
149     @SuppressWarnings("checkstyle:IllegalCatch")
150     public void start() {
151         try {
152             createIdPool();
153             registerEntityForOwnership();
154             itmStatusProvider.reportStatus(ServiceState.OPERATIONAL);
155             LOG.info("ItmProvider Started");
156         } catch (Exception ex) {
157             itmStatusProvider.reportStatus(ex);
158             LOG.info("ItmProvider failed to start", ex);
159             return;
160         }
161         createDefaultTransportZone(itmConfig);
162     }
163
164     public void createDefaultTransportZone(ItmConfig itmConfigObj) {
165         if (!entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY)) {
166             return;
167         }
168         jobCoordinator.enqueueJob(ITMConstants.DEFAULT_TRANSPORT_ZONE, () -> {
169             boolean defTzEnabled = itmConfigObj.isDefTzEnabled();
170             if (defTzEnabled) {
171                 String tunnelType = itmConfigObj.getDefTzTunnelType();
172                 if (tunnelType == null || tunnelType.isEmpty()) {
173                     tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN;
174                 }
175                 // validate tunnel-type and based on tunnel-type,
176                 // create default-TZ or update default-TZ if tunnel-type is changed during ODL restart
177                 configureTunnelType(ITMConstants.DEFAULT_TRANSPORT_ZONE, tunnelType);
178                 LOG.info("{} is created with {} tunnel-type.", ITMConstants.DEFAULT_TRANSPORT_ZONE, tunnelType);
179             } else {
180                 LOG.info("Removing {} on start-up, def-tz-enabled is false.", ITMConstants.DEFAULT_TRANSPORT_ZONE);
181                 // check if default-TZ already exists, then delete it because flag is OFF now.
182                 ItmUtils.deleteTransportZoneFromConfigDS(ITMConstants.DEFAULT_TRANSPORT_ZONE, dataBroker);
183             }
184             return Collections.emptyList();
185         });
186     }
187
188     private void registerEntityForOwnership() {
189         try {
190             this.registryCandidate = entityOwnershipService
191                     .registerCandidate(new Entity(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY));
192         } catch (CandidateAlreadyRegisteredException e) {
193             LOG.error("failed to register entity {} for entity-ownership-service", e.getEntity());
194         }
195     }
196
197     @Override
198     @PreDestroy
199     public void close() {
200         if (tzChangeListener != null) {
201             tzChangeListener.close();
202         }
203         if (tnlIntervalListener != null) {
204             tnlIntervalListener.close();
205         }
206         if (tnlToggleListener != null) {
207             tnlToggleListener.close();
208         }
209         if (ovsdbChangeListener != null) {
210             ovsdbChangeListener.close();
211         }
212         if (registryCandidate != null) {
213             registryCandidate.close();
214         }
215         itmStatusProvider.reportStatus(ServiceState.UNREGISTERED);
216         LOG.info("ItmProvider Closed");
217     }
218
219     private void createIdPool() {
220         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
221                 .setPoolName(ITMConstants.ITM_IDPOOL_NAME)
222                 .setLow(ITMConstants.ITM_IDPOOL_START)
223                 .setHigh(new BigInteger(ITMConstants.ITM_IDPOOL_SIZE).longValue())
224                 .build();
225         try {
226             ListenableFuture<RpcResult<CreateIdPoolOutput>> result = idManager.createIdPool(createPool);
227             if (result != null && result.get().isSuccessful()) {
228                 LOG.debug("Created IdPool for ITM Service");
229             }
230         } catch (InterruptedException | ExecutionException e) {
231             LOG.error("Failed to create idPool for ITM Service ", e);
232         }
233     }
234
235     @Override
236     public DataBroker getDataBroker() {
237         return dataBroker;
238     }
239
240     @Override
241     public void addExternalEndpoint(Class<? extends TunnelTypeBase> tunnelType, IpAddress dcgwIP) {
242         AddExternalTunnelEndpointInput addExternalTunnelEndpointInput =
243                 new AddExternalTunnelEndpointInputBuilder().setTunnelType(tunnelType)
244                         .setDestinationIp(dcgwIP).build();
245         JdkFutures.addErrorLogging(itmRpcService.addExternalTunnelEndpoint(addExternalTunnelEndpointInput),
246                 LOG, "addExternalTunnelEndpoint");
247     }
248
249     @Override
250     public void remExternalEndpoint(Class<? extends TunnelTypeBase> tunnelType, IpAddress dcgwIP) {
251         RemoveExternalTunnelEndpointInput removeExternalTunnelEndpointInput =
252                 new RemoveExternalTunnelEndpointInputBuilder().setTunnelType(tunnelType)
253                         .setDestinationIp(dcgwIP).build();
254         JdkFutures.addErrorLogging(itmRpcService.removeExternalTunnelEndpoint(removeExternalTunnelEndpointInput),
255                 LOG, "removeExternalTunnelEndpoint");
256     }
257
258     @Override
259     public void createLocalCache(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
260                                  String gatewayIp, String transportZone, CommandSession session) {
261         if (tepCommandHelper != null) {
262             try {
263                 tepCommandHelper.createLocalCache(dpnId, portName, vlanId, ipAddress, subnetMask,
264                         gatewayIp, transportZone, session);
265             } catch (TepException e) {
266                 LOG.error("Create Local Cache failed", e);
267             }
268         } else {
269             LOG.trace("tepCommandHelper doesnt exist");
270         }
271     }
272
273     @Override
274     public void commitTeps() {
275         tepCommandHelper.deleteOnCommit();
276         tepCommandHelper.buildTeps();
277     }
278
279     @Override
280     public void showTeps(CommandSession session) {
281         try {
282             tepCommandHelper.showTeps(tunnelMonitoringConfig.isTunnelMonitoringEnabled(),
283                     tunnelMonitoringConfig.getMonitorInterval(), session);
284         } catch (TepException e) {
285             LOG.error("show teps failed", e);
286         }
287     }
288
289     @Override
290     public void showState(Collection<StateTunnelList> tunnels) {
291         if (tunnels != null) {
292             try {
293                 tepCommandHelper.showState(tunnels, tunnelMonitoringConfig.isTunnelMonitoringEnabled());
294             } catch (TepException e) {
295                 LOG.error("show state failed", e);
296             }
297         } else {
298             LOG.debug("No tunnels available");
299         }
300     }
301
302     @Override
303     public void showCache(String cacheName) {
304         tepCommandHelper.showCache(cacheName);
305     }
306
307     @Override
308     public void deleteVtep(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
309                            String gatewayIp, String transportZone, CommandSession session) {
310         try {
311             tepCommandHelper.deleteVtep(dpnId,  portName, vlanId, ipAddress,
312                     subnetMask, gatewayIp, transportZone, session);
313         } catch (TepException e) {
314             LOG.error("Delete Vteps Failed", e);
315         }
316     }
317
318     @Override
319     public void configureTunnelType(String transportZone, String tunnelType) {
320         LOG.debug("ItmProvider: configureTunnelType {} for transportZone {}", tunnelType, transportZone);
321         try {
322             tepCommandHelper.configureTunnelType(transportZone,tunnelType);
323         } catch (ExecutionException | InterruptedException e) {
324             LOG.error("configureTunnelType {} failed for transportZone {}", tunnelType, transportZone, e);
325         }
326     }
327
328     @Override
329     public void addVtepConfigSchema(VtepConfigSchema vtepConfigSchema) {
330         VtepConfigSchema validatedSchema = ItmUtils.validateForAddVtepConfigSchema(vtepConfigSchema,
331                 getAllVtepConfigSchemas());
332
333         String schemaName = validatedSchema.getSchemaName();
334         VtepConfigSchema existingSchema = getVtepConfigSchema(schemaName);
335         if (existingSchema != null) {
336             Preconditions.checkArgument(false, String.format("VtepConfigSchema [%s] already exists!", schemaName));
337         }
338         MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION,
339                 ItmUtils.getVtepConfigSchemaIdentifier(schemaName), validatedSchema);
340         LOG.debug("Vtep config schema {} added to config DS", schemaName);
341     }
342
343     @Override
344     public VtepConfigSchema getVtepConfigSchema(String schemaName) {
345         return ItmUtils.read(LogicalDatastoreType.CONFIGURATION, ItmUtils.getVtepConfigSchemaIdentifier(schemaName),
346                 this.dataBroker).orNull();
347     }
348
349     @Override
350     public List<VtepConfigSchema> getAllVtepConfigSchemas() {
351         return ItmUtils.read(LogicalDatastoreType.CONFIGURATION, ItmUtils.getVtepConfigSchemasIdentifier(),
352                 this.dataBroker).toJavaUtil().map(VtepConfigSchemas::getVtepConfigSchema).orElse(null);
353     }
354
355     @Override
356     public void updateVtepSchema(String schemaName, List<BigInteger> lstDpnsForAdd, List<BigInteger> lstDpnsForDelete) {
357         LOG.trace("Updating VTEP schema {} by adding DPN's {} and deleting DPN's {}.", schemaName, lstDpnsForAdd,
358                 lstDpnsForDelete);
359
360         VtepConfigSchema schema = ItmUtils.validateForUpdateVtepSchema(schemaName, lstDpnsForAdd, lstDpnsForDelete,
361                 this);
362         VtepConfigSchemaBuilder builder = new VtepConfigSchemaBuilder(schema);
363        /* if (ItmUtils.getDpnIdList(schema.getDpnIds()).isEmpty()) {
364             builder.setDpnIds(schema.getDpnIds());
365         } else {*/
366         if (lstDpnsForAdd != null && !lstDpnsForAdd.isEmpty()) {
367             List<BigInteger> originalDpnList = ItmUtils.getDpnIdList(schema.getDpnIds());
368             originalDpnList.addAll(lstDpnsForAdd) ;
369             builder.setDpnIds(ItmUtils.getDpnIdsListFromBigInt(originalDpnList));
370         }
371         if (lstDpnsForDelete != null && !lstDpnsForDelete.isEmpty()) {
372             List<BigInteger> originalDpnList = ItmUtils.getDpnIdList(schema.getDpnIds());
373             originalDpnList.removeAll(lstDpnsForDelete) ;
374             builder.setDpnIds(ItmUtils.getDpnIdsListFromBigInt(originalDpnList));
375             // schema.setDpnIds(ItmUtils.getDpnIdsListFromBigInt(ItmUtils.getDpnIdList(schema.getDpnIds())
376             // .removeAll(lstDpnsForAdd)));
377         }
378         // }
379         schema = builder.build();
380         MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION,
381                 ItmUtils.getVtepConfigSchemaIdentifier(schemaName), schema);
382         LOG.debug("Vtep config schema {} updated to config DS with DPN's {}",
383                 schemaName, ItmUtils.getDpnIdList(schema.getDpnIds()));
384     }
385
386     @Override
387     public void deleteAllVtepSchemas() {
388         List<VtepConfigSchema> lstSchemas = getAllVtepConfigSchemas();
389         if (lstSchemas != null && !lstSchemas.isEmpty()) {
390             for (VtepConfigSchema schema : lstSchemas) {
391                 MDSALUtil.syncDelete(this.dataBroker, LogicalDatastoreType.CONFIGURATION,
392                         ItmUtils.getVtepConfigSchemaIdentifier(schema.getSchemaName()));
393             }
394         }
395         LOG.debug("Deleted all Vtep schemas from config DS");
396     }
397
398     @Override
399     public void configureTunnelMonitorParams(boolean monitorEnabled, String monitorProtocol) {
400         tepCommandHelper.configureTunnelMonitorParams(monitorEnabled, monitorProtocol);
401     }
402
403     @Override
404     public void configureTunnelMonitorInterval(int interval) {
405         tepCommandHelper.configureTunnelMonitorInterval(interval);
406     }
407
408     @Override
409     public boolean validateIP(final String ip) {
410         if (ip == null || ip.isEmpty() || "null".equals(ip) || "0.0.0.0".equals(ip)) {
411             return false;
412         }
413         final String PTRN =
414                 "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
415         Pattern pattern = Pattern.compile(PTRN);
416         Matcher matcher = pattern.matcher(ip);
417         return matcher.matches();
418     }
419
420     @Override
421     public Interface getInterface(String tunnelName) {
422         return dpnTepStateCache.getInterfaceFromCache(tunnelName);
423     }
424
425     @Override
426     public Optional<StateTunnelList> getTunnelState(String interfaceName) throws ReadFailedException {
427         return tunnelStateCache.get(tunnelStateCache.getStateTunnelListIdentifier(interfaceName));
428     }
429 }