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);
77 private final DataBroker dataBroker;
78 private final ItmManagerRpcService itmRpcService ;
79 private final IdManagerService idManager;
80 private final TepCommandHelper tepCommandHelper;
81 private final TransportZoneListener tzChangeListener;
82 private final TunnelMonitorChangeListener tnlToggleListener;
83 private final TunnelMonitorIntervalListener tnlIntervalListener;
84 private final InterfaceStateListener ifStateListener;
85 private final EntityOwnershipService entityOwnershipService;
86 private final ItmDiagStatusProvider itmStatusProvider;
87 private RpcProviderService rpcProviderService;
88 private final ItmTunnelEventListener itmStateListener;
89 private final OvsdbNodeListener ovsdbChangeListener;
90 static short flag = 0;
91 private final TunnelMonitoringConfig tunnelMonitoringConfig;
92 private EntityOwnershipCandidateRegistration registryCandidate;
93 private final DpnTepStateCache dpnTepStateCache;
94 private final TunnelStateCache tunnelStateCache;
95 private final ItmConfig itmConfig;
96 private final JobCoordinator jobCoordinator;
97 private final ItmProvider.ItmProviderEOSListener itmProviderEOSListener;
98 public Integer batchSize;
99 public Integer batchInterval;
100 private EosChangeEventHandler eosChangeEventHandler;
103 public ItmProvider(DataBroker dataBroker,
104 IdManagerService idManagerService,
105 InterfaceStateListener interfaceStateListener,
106 ItmManagerRpcService itmManagerRpcService,
107 ItmTunnelEventListener itmTunnelEventListener,
108 TepCommandHelper tepCommandHelper,
109 TunnelMonitorChangeListener tunnelMonitorChangeListener,
110 TunnelMonitorIntervalListener tunnelMonitorIntervalListener,
111 TransportZoneListener transportZoneListener,
112 OvsdbNodeListener ovsdbNodeListener,
113 TunnelMonitoringConfig tunnelMonitoringConfig,
114 EntityOwnershipService entityOwnershipService,
115 DpnTepStateCache dpnTepStateCache,
116 final ItmDiagStatusProvider itmDiagStatusProvider,
117 final TunnelStateCache tunnelStateCache,
118 final ItmConfig itmConfig,
119 final JobCoordinator jobCoordinator,
120 final EosChangeEventHandler eosChangeEventHandler) {
121 LOG.info("ItmProvider Before register MBean");
122 this.dataBroker = dataBroker;
123 this.idManager = idManagerService;
124 this.ifStateListener = interfaceStateListener;
125 this.itmRpcService = itmManagerRpcService;
126 this.itmStateListener = itmTunnelEventListener;
127 this.tepCommandHelper = tepCommandHelper;
128 this.tnlToggleListener = tunnelMonitorChangeListener;
129 this.tnlIntervalListener = tunnelMonitorIntervalListener;
130 this.tzChangeListener = transportZoneListener;
131 this.ovsdbChangeListener = ovsdbNodeListener;
132 this.tunnelMonitoringConfig = tunnelMonitoringConfig;
133 this.entityOwnershipService = entityOwnershipService;
134 this.dpnTepStateCache = dpnTepStateCache;
135 this.itmStatusProvider = itmDiagStatusProvider;
136 this.tunnelStateCache = tunnelStateCache;
137 this.eosChangeEventHandler = eosChangeEventHandler;
139 this.itmConfig = itmConfig;
140 this.jobCoordinator = jobCoordinator;
141 this.itmProviderEOSListener = new ItmProvider.ItmProviderEOSListener(this, this.entityOwnershipService);
145 @SuppressWarnings("checkstyle:IllegalCatch")
146 public void start() {
149 registerEntityForOwnership();
150 initialiseBatchingManager();
151 LOG.info("ItmProvider Started");
152 } catch (Exception ex) {
153 itmStatusProvider.reportStatus(ex);
154 LOG.info("ItmProvider failed to start", ex);
159 public void initialiseBatchingManager() {
160 batchSize = ITMConstants.BATCH_SIZE;
161 LOG.info("entered initialse");
162 if (itmConfig.getBatchSize() != null) {
163 batchSize = itmConfig.getBatchSize().toJava();
165 batchInterval = ITMConstants.PERIODICITY;
166 if (itmConfig.getBatchInterval() != null) {
167 batchInterval = itmConfig.getBatchInterval().toJava();
169 ITMBatchingUtils.registerWithBatchManager(this.dataBroker,this.batchSize,this.batchInterval);
172 public void createDefaultTransportZone(ItmConfig itmConfigObj) {
173 jobCoordinator.enqueueJob(ITMConstants.DEFAULT_TRANSPORT_ZONE, () -> {
174 boolean defTzEnabled = itmConfigObj.isDefTzEnabled();
176 String tunnelType = itmConfigObj.getDefTzTunnelType();
177 if (tunnelType == null || tunnelType.isEmpty()) {
178 tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN;
180 // validate tunnel-type and based on tunnel-type,
181 // create default-TZ or update default-TZ if tunnel-type is changed during ODL restart
182 configureTunnelType(ITMConstants.DEFAULT_TRANSPORT_ZONE, tunnelType);
183 LOG.info("{} is created with {} tunnel-type.", ITMConstants.DEFAULT_TRANSPORT_ZONE, tunnelType);
185 LOG.info("Removing {} on start-up, def-tz-enabled is false.", ITMConstants.DEFAULT_TRANSPORT_ZONE);
186 // check if default-TZ already exists, then delete it because flag is OFF now.
187 ItmUtils.deleteTransportZoneFromConfigDS(ITMConstants.DEFAULT_TRANSPORT_ZONE, dataBroker);
189 return Collections.emptyList();
193 private void registerEntityForOwnership() {
195 this.registryCandidate = entityOwnershipService
196 .registerCandidate(new Entity(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY));
197 } catch (CandidateAlreadyRegisteredException e) {
198 LOG.error("failed to register entity {} for entity-ownership-service", e.getEntity());
204 public void close() {
205 if (tzChangeListener != null) {
206 tzChangeListener.close();
208 if (tnlIntervalListener != null) {
209 tnlIntervalListener.close();
211 if (tnlToggleListener != null) {
212 tnlToggleListener.close();
214 if (ovsdbChangeListener != null) {
215 ovsdbChangeListener.close();
217 if (registryCandidate != null) {
218 registryCandidate.close();
220 itmStatusProvider.reportStatus(ServiceState.UNREGISTERED);
221 this.itmProviderEOSListener.close();
222 LOG.info("ItmProvider Closed");
225 private void createIdPool() {
226 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
227 .setPoolName(ITMConstants.ITM_IDPOOL_NAME)
228 .setLow(ITMConstants.ITM_IDPOOL_START)
229 .setHigh(Uint32.valueOf(ITMConstants.ITM_IDPOOL_SIZE))
232 ListenableFuture<RpcResult<CreateIdPoolOutput>> result = idManager.createIdPool(createPool);
233 if (result != null && result.get().isSuccessful()) {
234 LOG.debug("Created IdPool for ITM Service");
236 } catch (InterruptedException | ExecutionException e) {
237 LOG.error("Failed to create idPool for ITM Service ", e);
242 public DataBroker getDataBroker() {
247 public void addExternalEndpoint(Class<? extends TunnelTypeBase> tunnelType, IpAddress dcgwIP) {
248 AddExternalTunnelEndpointInput addExternalTunnelEndpointInput =
249 new AddExternalTunnelEndpointInputBuilder().setTunnelType(tunnelType)
250 .setDestinationIp(dcgwIP).build();
251 LoggingFutures.addErrorLogging(itmRpcService.addExternalTunnelEndpoint(addExternalTunnelEndpointInput),
252 LOG, "addExternalTunnelEndpoint");
256 public void remExternalEndpoint(Class<? extends TunnelTypeBase> tunnelType, IpAddress dcgwIP) {
257 RemoveExternalTunnelEndpointInput removeExternalTunnelEndpointInput =
258 new RemoveExternalTunnelEndpointInputBuilder().setTunnelType(tunnelType)
259 .setDestinationIp(dcgwIP).build();
260 LoggingFutures.addErrorLogging(itmRpcService.removeExternalTunnelEndpoint(removeExternalTunnelEndpointInput),
261 LOG, "removeExternalTunnelEndpoint");
265 public void createLocalCache(Uint64 dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
266 String gatewayIp, String transportZone) {
267 if (tepCommandHelper != null) {
269 tepCommandHelper.createLocalCache(dpnId, ipAddress, transportZone);
270 } catch (TepException e) {
271 LOG.error("Create Local Cache failed", e);
274 LOG.trace("tepCommandHelper doesnt exist");
279 public void commitTeps() {
280 tepCommandHelper.deleteOnCommit();
281 tepCommandHelper.buildTeps();
285 public List<String> showTeps() {
287 return tepCommandHelper.showTeps(tunnelMonitoringConfig.isTunnelMonitoringEnabled(),
288 tunnelMonitoringConfig.getMonitorInterval());
289 } catch (TepException e) {
290 LOG.error("show teps failed", e);
291 return Collections.singletonList(e.getMessage());
296 public void showState(Collection<StateTunnelList> tunnels) {
297 if (tunnels != null) {
299 tepCommandHelper.showState(tunnels, tunnelMonitoringConfig.isTunnelMonitoringEnabled());
300 } catch (TepException e) {
301 LOG.error("show state failed", e);
304 LOG.debug("No tunnels available");
309 public void showBridges(Map dpnIdBridgeRefsMap) {
310 if (!dpnIdBridgeRefsMap.isEmpty()) {
311 tepCommandHelper.showBridges(dpnIdBridgeRefsMap);
313 LOG.warn("tep:show-bridges => No bridges available");
318 public void showCache(String cacheName) {
319 tepCommandHelper.showCache(cacheName);
323 public void deleteVtep(Uint64 dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
324 String gatewayIp, String transportZone) {
326 tepCommandHelper.deleteVtep(dpnId, ipAddress, transportZone);
327 } catch (TepException e) {
328 LOG.error("Delete Vteps Failed", e);
333 public void configureTunnelType(String transportZone, String tunnelType) {
334 LOG.debug("ItmProvider: configureTunnelType {} for transportZone {}", tunnelType, transportZone);
336 tepCommandHelper.configureTunnelType(transportZone,tunnelType);
337 } catch (ExecutionException | InterruptedException e) {
338 LOG.error("configureTunnelType {} failed for transportZone {}", tunnelType, transportZone, e);
343 public void configureTunnelMonitorParams(boolean monitorEnabled, String monitorProtocol) {
344 tepCommandHelper.configureTunnelMonitorParams(monitorEnabled, monitorProtocol);
348 public void configureTunnelMonitorInterval(int interval) {
349 tepCommandHelper.configureTunnelMonitorInterval(interval);
353 public boolean validateIP(final String ip) {
354 if (ip == null || ip.isEmpty() || "null".equals(ip) || "0.0.0.0".equals(ip)) {
358 "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
359 Pattern pattern = Pattern.compile(PTRN);
360 Matcher matcher = pattern.matcher(ip);
361 return matcher.matches();
365 public Interface getInterface(String tunnelName) {
366 return dpnTepStateCache.getInterfaceFromCache(tunnelName);
370 public Optional<StateTunnelList> getTunnelState(String interfaceName) throws ReadFailedException {
371 return tunnelStateCache.get(tunnelStateCache.getStateTunnelListIdentifier(interfaceName));
374 public void handleOwnershipChange(EntityOwnershipChange ownershipChange,
375 EntityOwnershipListenerRegistration listenerRegistration) {
376 if (ownershipChange.getState().isOwner()) {
377 LOG.info("*This* instance of provider is set as a MASTER instance");
378 createDefaultTransportZone(itmConfig);
379 eosChangeEventHandler.recoverUnknownTunnelsOnEosSwitch();
381 LOG.info("*This* instance of provider is set as a SLAVE instance");
383 itmStatusProvider.reportStatus(ServiceState.OPERATIONAL);
384 if (listenerRegistration != null) {
385 listenerRegistration.close();
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);
398 public void close() {
399 listenerRegistration.close();
403 public void ownershipChanged(EntityOwnershipChange ownershipChange) {
404 itmProviderObj.handleOwnershipChange(ownershipChange, listenerRegistration);