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