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.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;
72 public class ItmProvider implements AutoCloseable, IITMProvider /*,ItmStateService */ {
74 private static final Logger LOG = LoggerFactory.getLogger(ItmProvider.class);
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;
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;
136 this.itmConfig = itmConfig;
137 this.jobCoordinator = jobCoordinator;
138 this.itmProviderEOSListener = new ItmProvider.ItmProviderEOSListener(this, this.entityOwnershipService);
142 @SuppressWarnings("checkstyle:IllegalCatch")
143 public void start() {
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);
156 public void initialiseBatchingManager() {
157 batchSize = ITMConstants.BATCH_SIZE;
158 LOG.info("entered initialse");
159 if (itmConfig.getBatchSize() != null) {
160 batchSize = itmConfig.getBatchSize().toJava();
162 batchInterval = ITMConstants.PERIODICITY;
163 if (itmConfig.getBatchInterval() != null) {
164 batchInterval = itmConfig.getBatchInterval().toJava();
166 ITMBatchingUtils.registerWithBatchManager(this.dataBroker,this.batchSize,this.batchInterval);
169 public void createDefaultTransportZone(ItmConfig itmConfigObj) {
170 jobCoordinator.enqueueJob(ITMConstants.DEFAULT_TRANSPORT_ZONE, () -> {
171 boolean defTzEnabled = itmConfigObj.isDefTzEnabled();
173 String tunnelType = itmConfigObj.getDefTzTunnelType();
174 if (tunnelType == null || tunnelType.isEmpty()) {
175 tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN;
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);
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);
186 return Collections.emptyList();
190 private void registerEntityForOwnership() {
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());
201 public void close() {
202 if (tzChangeListener != null) {
203 tzChangeListener.close();
205 if (tnlIntervalListener != null) {
206 tnlIntervalListener.close();
208 if (tnlToggleListener != null) {
209 tnlToggleListener.close();
211 if (ovsdbChangeListener != null) {
212 ovsdbChangeListener.close();
214 if (registryCandidate != null) {
215 registryCandidate.close();
217 itmStatusProvider.reportStatus(ServiceState.UNREGISTERED);
218 this.itmProviderEOSListener.close();
219 LOG.info("ItmProvider Closed");
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))
229 ListenableFuture<RpcResult<CreateIdPoolOutput>> result = idManager.createIdPool(createPool);
230 if (result != null && result.get().isSuccessful()) {
231 LOG.debug("Created IdPool for ITM Service");
233 } catch (InterruptedException | ExecutionException e) {
234 LOG.error("Failed to create idPool for ITM Service ", e);
239 public DataBroker getDataBroker() {
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");
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");
262 public void createLocalCache(Uint64 dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
263 String gatewayIp, String transportZone) {
264 if (tepCommandHelper != null) {
266 tepCommandHelper.createLocalCache(dpnId, ipAddress, transportZone);
267 } catch (TepException e) {
268 LOG.error("Create Local Cache failed", e);
271 LOG.trace("tepCommandHelper doesnt exist");
276 public void commitTeps() {
277 tepCommandHelper.deleteOnCommit();
278 tepCommandHelper.buildTeps();
282 public List<String> showTeps() {
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());
293 public void showState(Collection<StateTunnelList> tunnels) {
294 if (tunnels != null) {
296 tepCommandHelper.showState(tunnels, tunnelMonitoringConfig.isTunnelMonitoringEnabled());
297 } catch (TepException e) {
298 LOG.error("show state failed", e);
301 LOG.debug("No tunnels available");
306 public void showBridges(Map dpnIdBridgeRefsMap) {
307 if (!dpnIdBridgeRefsMap.isEmpty()) {
308 tepCommandHelper.showBridges(dpnIdBridgeRefsMap);
310 LOG.warn("tep:show-bridges => No bridges available");
315 public void showCache(String cacheName) {
316 tepCommandHelper.showCache(cacheName);
320 public void deleteVtep(Uint64 dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
321 String gatewayIp, String transportZone) {
323 tepCommandHelper.deleteVtep(dpnId, ipAddress, transportZone);
324 } catch (TepException e) {
325 LOG.error("Delete Vteps Failed", e);
330 public void configureTunnelType(String transportZone, String tunnelType) {
331 LOG.debug("ItmProvider: configureTunnelType {} for transportZone {}", tunnelType, transportZone);
333 tepCommandHelper.configureTunnelType(transportZone,tunnelType);
334 } catch (ExecutionException | InterruptedException e) {
335 LOG.error("configureTunnelType {} failed for transportZone {}", tunnelType, transportZone, e);
340 public void configureTunnelMonitorParams(boolean monitorEnabled, String monitorProtocol) {
341 tepCommandHelper.configureTunnelMonitorParams(monitorEnabled, monitorProtocol);
345 public void configureTunnelMonitorInterval(int interval) {
346 tepCommandHelper.configureTunnelMonitorInterval(interval);
350 public boolean validateIP(final String ip) {
351 if (ip == null || ip.isEmpty() || "null".equals(ip) || "0.0.0.0".equals(ip)) {
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();
362 public Interface getInterface(String tunnelName) {
363 return dpnTepStateCache.getInterfaceFromCache(tunnelName);
367 public Optional<StateTunnelList> getTunnelState(String interfaceName) throws ReadFailedException {
368 return tunnelStateCache.get(tunnelStateCache.getStateTunnelListIdentifier(interfaceName));
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);
377 LOG.info("*This* instance of provider is set as a SLAVE instance");
379 itmStatusProvider.reportStatus(ServiceState.OPERATIONAL);
380 if (listenerRegistration != null) {
381 listenerRegistration.close();
385 private static class ItmProviderEOSListener implements EntityOwnershipListener {
386 private final ItmProvider itmProviderObj;
387 private final EntityOwnershipListenerRegistration listenerRegistration;
389 ItmProviderEOSListener(ItmProvider itmProviderObj, EntityOwnershipService entityOwnershipService) {
390 this.itmProviderObj = itmProviderObj;
391 this.listenerRegistration = entityOwnershipService.registerListener(ITMConstants.ITM_CONFIG_ENTITY, this);
394 public void close() {
395 listenerRegistration.close();
399 public void ownershipChanged(EntityOwnershipChange ownershipChange) {
400 itmProviderObj.handleOwnershipChange(ownershipChange, listenerRegistration);