2 * Copyright (c) 2016, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.genius.itm.impl;
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.util.Collection;
12 import java.util.Collections;
13 import java.util.List;
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.tunnels_state.StateTunnelList;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddExternalTunnelEndpointInputBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveExternalTunnelEndpointInputBuilder;
65 import org.opendaylight.yangtools.yang.common.RpcResult;
66 import org.opendaylight.yangtools.yang.common.Uint32;
67 import org.opendaylight.yangtools.yang.common.Uint64;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
73 public class ItmProvider implements AutoCloseable, IITMProvider /*,ItmStateService */ {
75 private static final Logger LOG = LoggerFactory.getLogger(ItmProvider.class);
76 private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
78 private final DataBroker dataBroker;
79 private final ItmManagerRpcService itmRpcService ;
80 private final IdManagerService idManager;
81 private final TepCommandHelper tepCommandHelper;
82 private final TransportZoneListener tzChangeListener;
83 private final TunnelMonitorChangeListener tnlToggleListener;
84 private final TunnelMonitorIntervalListener tnlIntervalListener;
85 private final InterfaceStateListener ifStateListener;
86 private final EntityOwnershipService entityOwnershipService;
87 private final ItmDiagStatusProvider itmStatusProvider;
88 private RpcProviderService rpcProviderService;
89 private final ItmTunnelEventListener itmStateListener;
90 private final OvsdbNodeListener ovsdbChangeListener;
91 static short flag = 0;
92 private final TunnelMonitoringConfig tunnelMonitoringConfig;
93 private EntityOwnershipCandidateRegistration registryCandidate;
94 private final DpnTepStateCache dpnTepStateCache;
95 private final TunnelStateCache tunnelStateCache;
96 private final ItmConfig itmConfig;
97 private final JobCoordinator jobCoordinator;
98 private final ItmProvider.ItmProviderEOSListener itmProviderEOSListener;
99 public Integer batchSize;
100 public Integer batchInterval;
101 private EosChangeEventHandler eosChangeEventHandler;
104 public ItmProvider(DataBroker dataBroker,
105 IdManagerService idManagerService,
106 InterfaceStateListener interfaceStateListener,
107 ItmManagerRpcService itmManagerRpcService,
108 ItmTunnelEventListener itmTunnelEventListener,
109 TepCommandHelper tepCommandHelper,
110 TunnelMonitorChangeListener tunnelMonitorChangeListener,
111 TunnelMonitorIntervalListener tunnelMonitorIntervalListener,
112 TransportZoneListener transportZoneListener,
113 OvsdbNodeListener ovsdbNodeListener,
114 TunnelMonitoringConfig tunnelMonitoringConfig,
115 EntityOwnershipService entityOwnershipService,
116 DpnTepStateCache dpnTepStateCache,
117 final ItmDiagStatusProvider itmDiagStatusProvider,
118 final TunnelStateCache tunnelStateCache,
119 final ItmConfig itmConfig,
120 final JobCoordinator jobCoordinator,
121 final EosChangeEventHandler eosChangeEventHandler) {
122 LOG.info("ItmProvider Before register MBean");
123 this.dataBroker = dataBroker;
124 this.idManager = idManagerService;
125 this.ifStateListener = interfaceStateListener;
126 this.itmRpcService = itmManagerRpcService;
127 this.itmStateListener = itmTunnelEventListener;
128 this.tepCommandHelper = tepCommandHelper;
129 this.tnlToggleListener = tunnelMonitorChangeListener;
130 this.tnlIntervalListener = tunnelMonitorIntervalListener;
131 this.tzChangeListener = transportZoneListener;
132 this.ovsdbChangeListener = ovsdbNodeListener;
133 this.tunnelMonitoringConfig = tunnelMonitoringConfig;
134 this.entityOwnershipService = entityOwnershipService;
135 this.dpnTepStateCache = dpnTepStateCache;
136 this.itmStatusProvider = itmDiagStatusProvider;
137 this.tunnelStateCache = tunnelStateCache;
138 this.eosChangeEventHandler = eosChangeEventHandler;
140 this.itmConfig = itmConfig;
141 this.jobCoordinator = jobCoordinator;
142 this.itmProviderEOSListener = new ItmProvider.ItmProviderEOSListener(this, this.entityOwnershipService);
146 @SuppressWarnings("checkstyle:IllegalCatch")
147 public void start() {
150 registerEntityForOwnership();
151 initialiseBatchingManager();
152 LOG.info("ItmProvider Started");
153 } catch (Exception ex) {
154 itmStatusProvider.reportStatus(ex);
155 LOG.info("ItmProvider failed to start", ex);
160 public void initialiseBatchingManager() {
161 batchSize = ITMConstants.BATCH_SIZE;
162 LOG.info("entered initialse");
163 if (itmConfig.getBatchSize() != null) {
164 batchSize = itmConfig.getBatchSize().toJava();
166 batchInterval = ITMConstants.PERIODICITY;
167 if (itmConfig.getBatchInterval() != null) {
168 batchInterval = itmConfig.getBatchInterval().toJava();
170 ITMBatchingUtils.registerWithBatchManager(this.dataBroker,this.batchSize,this.batchInterval);
173 public void createDefaultTransportZone(ItmConfig itmConfigObj) {
174 jobCoordinator.enqueueJob(ITMConstants.DEFAULT_TRANSPORT_ZONE, () -> {
175 boolean defTzEnabled = itmConfigObj.isDefTzEnabled();
177 String tunnelType = itmConfigObj.getDefTzTunnelType();
178 if (tunnelType == null || tunnelType.isEmpty()) {
179 tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN;
181 // validate tunnel-type and based on tunnel-type,
182 // create default-TZ or update default-TZ if tunnel-type is changed during ODL restart
183 configureTunnelType(ITMConstants.DEFAULT_TRANSPORT_ZONE, tunnelType);
184 LOG.info("{} is created with {} tunnel-type.", ITMConstants.DEFAULT_TRANSPORT_ZONE, tunnelType);
186 LOG.info("Removing {} on start-up, def-tz-enabled is false.", ITMConstants.DEFAULT_TRANSPORT_ZONE);
187 // check if default-TZ already exists, then delete it because flag is OFF now.
188 ItmUtils.deleteTransportZoneFromConfigDS(ITMConstants.DEFAULT_TRANSPORT_ZONE, dataBroker);
190 return Collections.emptyList();
194 private void registerEntityForOwnership() {
196 this.registryCandidate = entityOwnershipService
197 .registerCandidate(new Entity(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY));
198 } catch (CandidateAlreadyRegisteredException e) {
199 LOG.error("failed to register entity {} for entity-ownership-service", e.getEntity());
205 public void close() {
206 if (tzChangeListener != null) {
207 tzChangeListener.close();
209 if (tnlIntervalListener != null) {
210 tnlIntervalListener.close();
212 if (tnlToggleListener != null) {
213 tnlToggleListener.close();
215 if (ovsdbChangeListener != null) {
216 ovsdbChangeListener.close();
218 if (registryCandidate != null) {
219 registryCandidate.close();
221 itmStatusProvider.reportStatus(ServiceState.UNREGISTERED);
222 this.itmProviderEOSListener.close();
223 LOG.info("ItmProvider Closed");
226 private void createIdPool() {
227 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
228 .setPoolName(ITMConstants.ITM_IDPOOL_NAME)
229 .setLow(ITMConstants.ITM_IDPOOL_START)
230 .setHigh(Uint32.valueOf(ITMConstants.ITM_IDPOOL_SIZE))
233 ListenableFuture<RpcResult<CreateIdPoolOutput>> result = idManager.createIdPool(createPool);
234 if (result != null && result.get().isSuccessful()) {
235 LOG.debug("Created IdPool for ITM Service");
237 } catch (InterruptedException | ExecutionException e) {
238 LOG.error("Failed to create idPool for ITM Service ", e);
243 public DataBroker getDataBroker() {
248 public void addExternalEndpoint(Class<? extends TunnelTypeBase> tunnelType, IpAddress dcgwIP) {
249 AddExternalTunnelEndpointInput addExternalTunnelEndpointInput =
250 new AddExternalTunnelEndpointInputBuilder().setTunnelType(tunnelType)
251 .setDestinationIp(dcgwIP).build();
252 LoggingFutures.addErrorLogging(itmRpcService.addExternalTunnelEndpoint(addExternalTunnelEndpointInput),
253 LOG, "addExternalTunnelEndpoint");
257 public void remExternalEndpoint(Class<? extends TunnelTypeBase> tunnelType, IpAddress dcgwIP) {
258 RemoveExternalTunnelEndpointInput removeExternalTunnelEndpointInput =
259 new RemoveExternalTunnelEndpointInputBuilder().setTunnelType(tunnelType)
260 .setDestinationIp(dcgwIP).build();
261 LoggingFutures.addErrorLogging(itmRpcService.removeExternalTunnelEndpoint(removeExternalTunnelEndpointInput),
262 LOG, "removeExternalTunnelEndpoint");
266 public void createLocalCache(Uint64 dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
267 String gatewayIp, String transportZone) {
268 if (tepCommandHelper != null) {
270 tepCommandHelper.createLocalCache(dpnId, ipAddress, transportZone);
271 } catch (TepException e) {
272 LOG.error("Create Local Cache failed", e);
275 LOG.trace("tepCommandHelper doesnt exist");
280 public void commitTeps() {
281 tepCommandHelper.deleteOnCommit();
282 tepCommandHelper.buildTeps();
286 public List<String> showTeps() {
288 return tepCommandHelper.showTeps(tunnelMonitoringConfig.isTunnelMonitoringEnabled(),
289 tunnelMonitoringConfig.getMonitorInterval());
290 } catch (TepException e) {
291 LOG.error("show teps failed", e);
292 return Collections.singletonList(e.getMessage());
297 public void showState(Collection<StateTunnelList> tunnels) {
298 if (tunnels != null) {
300 tepCommandHelper.showState(tunnels, tunnelMonitoringConfig.isTunnelMonitoringEnabled());
301 } catch (TepException e) {
302 LOG.error("show state failed", e);
305 LOG.debug("No tunnels available");
310 public void showBridges(Map dpnIdBridgeRefsMap) {
311 if (!dpnIdBridgeRefsMap.isEmpty()) {
312 tepCommandHelper.showBridges(dpnIdBridgeRefsMap);
314 LOG.warn("tep:show-bridges => No bridges available");
319 public void showCache(String cacheName) {
320 tepCommandHelper.showCache(cacheName);
324 public void deleteVtep(Uint64 dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
325 String gatewayIp, String transportZone) {
327 tepCommandHelper.deleteVtep(dpnId, ipAddress, transportZone);
328 } catch (TepException e) {
329 LOG.error("Delete Vteps Failed", e);
334 public void configureTunnelType(String transportZone, String tunnelType) {
335 LOG.debug("ItmProvider: configureTunnelType {} for transportZone {}", tunnelType, transportZone);
337 tepCommandHelper.configureTunnelType(transportZone,tunnelType);
338 } catch (ExecutionException | InterruptedException e) {
339 LOG.error("configureTunnelType {} failed for transportZone {}", tunnelType, transportZone, e);
344 public void configureTunnelMonitorParams(boolean monitorEnabled, String monitorProtocol) {
345 tepCommandHelper.configureTunnelMonitorParams(monitorEnabled, monitorProtocol);
349 public void configureTunnelMonitorInterval(int interval) {
350 tepCommandHelper.configureTunnelMonitorInterval(interval);
354 public boolean validateIP(final String ip) {
355 if (ip == null || ip.isEmpty() || "null".equals(ip) || "0.0.0.0".equals(ip)) {
359 "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
360 Pattern pattern = Pattern.compile(PTRN);
361 Matcher matcher = pattern.matcher(ip);
362 return matcher.matches();
366 public Interface getInterface(String tunnelName) {
367 return dpnTepStateCache.getInterfaceFromCache(tunnelName);
371 public Optional<StateTunnelList> getTunnelState(String interfaceName) throws ReadFailedException {
372 return tunnelStateCache.get(tunnelStateCache.getStateTunnelListIdentifier(interfaceName));
375 public void handleOwnershipChange(EntityOwnershipChange ownershipChange,
376 EntityOwnershipListenerRegistration listenerRegistration) {
377 if (ownershipChange.getState().isOwner()) {
378 LOG.info("*This* instance of provider is set as a MASTER instance");
379 EVENT_LOGGER.debug("****MASTER**** instance");
380 createDefaultTransportZone(itmConfig);
381 eosChangeEventHandler.recoverUnknownTunnelsOnEosSwitch();
383 LOG.info("*This* instance of provider is set as a SLAVE instance");
384 EVENT_LOGGER.debug("****SLAVE**** instance");
386 itmStatusProvider.reportStatus(ServiceState.OPERATIONAL);
389 private static class ItmProviderEOSListener implements EntityOwnershipListener {
390 private final ItmProvider itmProviderObj;
391 private final EntityOwnershipListenerRegistration listenerRegistration;
393 ItmProviderEOSListener(ItmProvider itmProviderObj, EntityOwnershipService entityOwnershipService) {
394 this.itmProviderObj = itmProviderObj;
395 this.listenerRegistration = entityOwnershipService.registerListener(ITMConstants.ITM_CONFIG_ENTITY, this);
396 EVENT_LOGGER.debug("ItmProviderEOSListener: registered");
399 public void close() {
400 listenerRegistration.close();
404 public void ownershipChanged(EntityOwnershipChange ownershipChange) {
405 EVENT_LOGGER.debug("****ownershipChanged****");
406 itmProviderObj.handleOwnershipChange(ownershipChange, listenerRegistration);