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.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;
74 public class ItmProvider implements AutoCloseable, IITMProvider /*,ItmStateService */ {
76 private static final Logger LOG = LoggerFactory.getLogger(ItmProvider.class);
77 private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
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;
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;
141 this.itmConfig = itmConfig;
142 this.jobCoordinator = jobCoordinator;
143 this.itmProviderEOSListener = new ItmProvider.ItmProviderEOSListener(this, this.entityOwnershipService);
147 @SuppressWarnings("checkstyle:IllegalCatch")
148 public void start() {
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);
161 public void initialiseBatchingManager() {
162 batchSize = ITMConstants.BATCH_SIZE;
163 LOG.info("entered initialse");
164 if (itmConfig.getBatchSize() != null) {
165 batchSize = itmConfig.getBatchSize().toJava();
167 batchInterval = ITMConstants.PERIODICITY;
168 if (itmConfig.getBatchInterval() != null) {
169 batchInterval = itmConfig.getBatchInterval().toJava();
171 ITMBatchingUtils.registerWithBatchManager(this.dataBroker,this.batchSize,this.batchInterval);
174 public void createDefaultTransportZone(ItmConfig itmConfigObj) {
175 jobCoordinator.enqueueJob(ITMConstants.DEFAULT_TRANSPORT_ZONE, () -> {
176 boolean defTzEnabled = itmConfigObj.isDefTzEnabled();
178 String tunnelType = itmConfigObj.getDefTzTunnelType();
179 if (tunnelType == null || tunnelType.isEmpty()) {
180 tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN;
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);
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);
191 return Collections.emptyList();
195 private void registerEntityForOwnership() {
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());
206 public void close() {
207 if (tzChangeListener != null) {
208 tzChangeListener.close();
210 if (tnlIntervalListener != null) {
211 tnlIntervalListener.close();
213 if (tnlToggleListener != null) {
214 tnlToggleListener.close();
216 if (ovsdbChangeListener != null) {
217 ovsdbChangeListener.close();
219 if (registryCandidate != null) {
220 registryCandidate.close();
222 itmStatusProvider.reportStatus(ServiceState.UNREGISTERED);
223 this.itmProviderEOSListener.close();
224 LOG.info("ItmProvider Closed");
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))
234 ListenableFuture<RpcResult<CreateIdPoolOutput>> result = idManager.createIdPool(createPool);
235 if (result != null && result.get().isSuccessful()) {
236 LOG.debug("Created IdPool for ITM Service");
238 } catch (InterruptedException | ExecutionException e) {
239 LOG.error("Failed to create idPool for ITM Service ", e);
244 public DataBroker getDataBroker() {
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");
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");
267 public void createLocalCache(Uint64 dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
268 String gatewayIp, String transportZone) {
269 if (tepCommandHelper != null) {
271 tepCommandHelper.createLocalCache(dpnId, ipAddress, transportZone);
272 } catch (TepException e) {
273 LOG.error("Create Local Cache failed", e);
276 LOG.trace("tepCommandHelper doesnt exist");
281 public void commitTeps() {
282 tepCommandHelper.deleteOnCommit();
283 tepCommandHelper.buildTeps();
287 public List<String> showTeps() {
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());
298 public void showState(Collection<StateTunnelList> tunnels) {
299 if (tunnels != null) {
301 tepCommandHelper.showState(tunnels, tunnelMonitoringConfig.isTunnelMonitoringEnabled());
302 } catch (TepException e) {
303 LOG.error("show state failed", e);
306 LOG.debug("No tunnels available");
311 public void showBridges(Map dpnIdBridgeRefsMap) {
312 if (!dpnIdBridgeRefsMap.isEmpty()) {
313 tepCommandHelper.showBridges(dpnIdBridgeRefsMap);
315 LOG.warn("tep:show-bridges => No bridges available");
320 public void showCache(String cacheName) {
321 tepCommandHelper.showCache(cacheName);
325 public void deleteVtep(Uint64 dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
326 String gatewayIp, String transportZone) {
328 tepCommandHelper.deleteVtep(dpnId, ipAddress, transportZone);
329 } catch (TepException e) {
330 LOG.error("Delete Vteps Failed", e);
335 public void configureTunnelType(String transportZone, String tunnelType) {
336 LOG.debug("ItmProvider: configureTunnelType {} for transportZone {}", tunnelType, transportZone);
338 tepCommandHelper.configureTunnelType(transportZone,tunnelType);
339 } catch (ExecutionException | InterruptedException e) {
340 LOG.error("configureTunnelType {} failed for transportZone {}", tunnelType, transportZone, e);
345 public void configureTunnelMonitorParams(boolean monitorEnabled, String monitorProtocol) {
346 tepCommandHelper.configureTunnelMonitorParams(monitorEnabled, monitorProtocol);
350 public void configureTunnelMonitorInterval(int interval) {
351 tepCommandHelper.configureTunnelMonitorInterval(interval);
355 public boolean validateIP(final String ip) {
356 if (ip == null || ip.isEmpty() || "null".equals(ip) || "0.0.0.0".equals(ip)) {
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();
367 public Interface getInterface(String tunnelName) {
368 return dpnTepStateCache.getInterfaceFromCache(tunnelName);
372 public Optional<StateTunnelList> getTunnelState(String interfaceName) throws ReadFailedException {
373 return tunnelStateCache.get(tunnelStateCache.getStateTunnelListIdentifier(interfaceName));
377 public void showOfPorts(Collection<OfTep> ofTeps) {
378 if (ofTeps != null) {
379 tepCommandHelper.showOfPorts(ofTeps); }
381 LOG.debug("No ofports available"); }
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();
392 LOG.info("*This* instance of provider is set as a SLAVE instance");
393 EVENT_LOGGER.debug("****SLAVE**** instance");
395 itmStatusProvider.reportStatus(ServiceState.OPERATIONAL);
398 private static class ItmProviderEOSListener implements EntityOwnershipListener {
399 private final ItmProvider itmProviderObj;
400 private final EntityOwnershipListenerRegistration listenerRegistration;
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");
408 public void close() {
409 listenerRegistration.close();
413 public void ownershipChanged(EntityOwnershipChange ownershipChange) {
414 EVENT_LOGGER.debug("****ownershipChanged****");
415 itmProviderObj.handleOwnershipChange(ownershipChange, listenerRegistration);