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