2 * Copyright (c) 2016 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
9 package org.opendaylight.genius.itm.listeners;
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.List;
19 import java.util.concurrent.ConcurrentHashMap;
20 import javax.annotation.PostConstruct;
21 import javax.annotation.PreDestroy;
22 import javax.inject.Inject;
23 import javax.inject.Singleton;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
28 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
29 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
30 import org.opendaylight.genius.itm.confighelpers.HwVtep;
31 import org.opendaylight.genius.itm.confighelpers.ItmTepAddWorker;
32 import org.opendaylight.genius.itm.confighelpers.ItmTepRemoveWorker;
33 import org.opendaylight.genius.itm.impl.ITMManager;
34 import org.opendaylight.genius.itm.impl.ItmUtils;
35 import org.opendaylight.genius.itm.validator.TransportZoneNameAllowed;
36 import org.opendaylight.genius.itm.validator.TransportZoneValidator;
37 import org.opendaylight.genius.itm.validator.ValidatorErrorCode;
38 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZonesBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVteps;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
52 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
57 * This class listens for interface creation/removal/update in Configuration DS.
58 * This is used to handle interfaces for base of-ports.
61 public class TransportZoneListener extends AsyncDataTreeChangeListenerBase<TransportZone, TransportZoneListener>
62 implements AutoCloseable {
63 private static final Logger LOG = LoggerFactory.getLogger(TransportZoneListener.class);
64 private final DataBroker dataBroker;
65 private final IdManagerService idManagerService;
66 private final IMdsalApiManager mdsalManager;
67 private final ITMManager itmManager;
70 public TransportZoneListener(final DataBroker dataBroker, final IdManagerService idManagerService,
71 final IMdsalApiManager iMdsalApiManager,final ITMManager itmManager) {
72 super(TransportZone.class, TransportZoneListener.class);
73 this.dataBroker = dataBroker;
74 this.idManagerService = idManagerService;
75 initializeTZNode(dataBroker);
76 this.itmManager = itmManager;
77 this.mdsalManager = iMdsalApiManager;
81 public void start() throws Exception {
82 registerListener(LogicalDatastoreType.CONFIGURATION, this.dataBroker);
83 LOG.info("tzChangeListener Started");
88 public void close() throws Exception {
89 LOG.info("tzChangeListener Closed");
92 private void initializeTZNode(DataBroker db) {
93 ReadWriteTransaction transaction = db.newReadWriteTransaction();
94 InstanceIdentifier<TransportZones> path = InstanceIdentifier.create(TransportZones.class);
95 CheckedFuture<Optional<TransportZones>, ReadFailedException> tzones = transaction
96 .read(LogicalDatastoreType.CONFIGURATION, path);
98 if (!tzones.get().isPresent()) {
99 TransportZonesBuilder tzb = new TransportZonesBuilder();
100 transaction.put(LogicalDatastoreType.CONFIGURATION, path, tzb.build());
101 transaction.submit();
103 transaction.cancel();
105 } catch (Exception e) {
106 LOG.error("Error initializing TransportZones {}", e);
111 protected InstanceIdentifier<TransportZone> getWildCardPath() {
112 return InstanceIdentifier.create(TransportZones.class).child(TransportZone.class);
116 protected TransportZoneListener getDataTreeChangeListener() {
117 return TransportZoneListener.this;
121 protected void remove(InstanceIdentifier<TransportZone> key, TransportZone tzOld) {
122 LOG.debug("Received Transport Zone Remove Event: {}, {}", key, tzOld);
123 if(validateTransportZoneParam(tzOld)){
124 //TODO : DPList code can be refactor with new specific class
125 // which implement TransportZoneValidator
126 List<DPNTEPsInfo> opDpnList = createDPNTepInfo(tzOld);
127 List<HwVtep> hwVtepList = createhWVteps(tzOld);
128 LOG.trace("Delete: Invoking deleteTunnels in ItmManager with DpnList {}", opDpnList);
129 if(!opDpnList.isEmpty() || !hwVtepList.isEmpty()) {
130 LOG.trace("Delete: Invoking ItmManager with hwVtep List {} " , hwVtepList);
131 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
132 ItmTepRemoveWorker removeWorker =
133 new ItmTepRemoveWorker(opDpnList, hwVtepList, tzOld, dataBroker, idManagerService, mdsalManager);
134 coordinator.enqueueJob(tzOld.getZoneName(), removeWorker);
140 protected void update(InstanceIdentifier<TransportZone> key, TransportZone tzOld, TransportZone tzNew) {
141 LOG.debug("Received Transport Zone Update Event: Key - {}, Old - {}, Updated - {}", key, tzOld, tzNew);
142 List<DPNTEPsInfo> oldDpnTepsList = createDPNTepInfo(tzOld);
143 List<DPNTEPsInfo> newDpnTepsList = createDPNTepInfo(tzNew);
144 List<DPNTEPsInfo> oldDpnTepsListcopy = new ArrayList<>();
145 oldDpnTepsListcopy.addAll(oldDpnTepsList);
146 LOG.trace("oldcopy0" + oldDpnTepsListcopy);
147 List<DPNTEPsInfo> newDpnTepsListcopy = new ArrayList<>();
148 newDpnTepsListcopy.addAll(newDpnTepsList);
149 LOG.trace("newcopy0" + newDpnTepsListcopy);
150 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
152 oldDpnTepsList.removeAll(newDpnTepsListcopy);
153 newDpnTepsList.removeAll(oldDpnTepsListcopy);
155 LOG.trace("oldDpnTepsList" + oldDpnTepsList);
156 LOG.trace("newDpnTepsList" + newDpnTepsList);
157 LOG.trace("oldcopy" + oldDpnTepsListcopy);
158 LOG.trace("newcopy" + newDpnTepsListcopy);
159 LOG.trace("oldcopy Size " + oldDpnTepsList.size());
160 LOG.trace("newcopy Size " + newDpnTepsList.size());
161 if (!newDpnTepsList.isEmpty()) {
162 LOG.trace("Adding TEPs ");
163 ItmTepAddWorker addWorker = new ItmTepAddWorker(newDpnTepsList, Collections.emptyList(), dataBroker,
164 idManagerService, mdsalManager);
165 coordinator.enqueueJob(tzNew.getZoneName(), addWorker);
167 if (!oldDpnTepsList.isEmpty()) {
168 LOG.trace("Removing TEPs ");
169 ItmTepRemoveWorker removeWorker = new ItmTepRemoveWorker(oldDpnTepsList, Collections.emptyList(),
170 tzOld, dataBroker, idManagerService, mdsalManager);
171 coordinator.enqueueJob(tzNew.getZoneName(), removeWorker);
173 List<HwVtep> oldHwList = createhWVteps(tzOld);
174 List<HwVtep> newHwList = createhWVteps(tzNew);
175 List<HwVtep> oldHwListcopy = new ArrayList<>();
176 oldHwListcopy.addAll(oldHwList);
177 LOG.trace("oldHwListcopy0" + oldHwListcopy);
178 List<HwVtep> newHwListcopy = new ArrayList<>();
179 newHwListcopy.addAll(newHwList);
180 LOG.trace("newHwListcopy0" + newHwListcopy);
182 oldHwList.removeAll(newHwListcopy);
183 newHwList.removeAll(oldHwListcopy);
184 LOG.trace("oldHwList" + oldHwList);
185 LOG.trace("newHwList" + newHwList);
186 LOG.trace("oldHwListcopy" + oldHwListcopy);
187 LOG.trace("newHwListcopy" + newHwListcopy);
188 if (!newHwList.isEmpty()) {
189 LOG.trace("Adding HW TEPs ");
190 ItmTepAddWorker addWorker = new ItmTepAddWorker(Collections.emptyList(), newHwList, dataBroker,
191 idManagerService, mdsalManager);
192 coordinator.enqueueJob(tzNew.getZoneName(), addWorker);
194 if (!oldHwList.isEmpty()) {
195 LOG.trace("Removing HW TEPs ");
196 ItmTepRemoveWorker removeWorker = new ItmTepRemoveWorker(Collections.emptyList(), oldHwList,
197 tzOld, dataBroker, idManagerService, mdsalManager);
198 coordinator.enqueueJob(tzNew.getZoneName(), removeWorker);
203 protected void add(InstanceIdentifier<TransportZone> key, TransportZone tzNew) {
204 LOG.debug("Received Transport Zone Add Event: {}, {}", key, tzNew);
205 List<DPNTEPsInfo> opDpnList = createDPNTepInfo(tzNew);
206 List<HwVtep> hwVtepList = createhWVteps(tzNew);
207 LOG.trace("Add: Operational dpnTepInfo - Before invoking ItmManager {}", opDpnList);
208 if (!opDpnList.isEmpty() || !hwVtepList.isEmpty()) {
209 LOG.trace("Add: Invoking ItmManager with DPN List {} ", opDpnList);
210 LOG.trace("Add: Invoking ItmManager with hwVtep List {} ", hwVtepList);
211 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
212 ItmTepAddWorker addWorker = new ItmTepAddWorker(opDpnList, hwVtepList, dataBroker, idManagerService,
214 coordinator.enqueueJob(tzNew.getZoneName(), addWorker);
218 private List<DPNTEPsInfo> createDPNTepInfo(TransportZone transportZone) {
219 Map<BigInteger, List<TunnelEndPoints>> mapDPNToTunnelEndpt = new ConcurrentHashMap<>();
220 List<DPNTEPsInfo> dpnTepInfo = new ArrayList<>();
221 List<TzMembership> zones = ItmUtils.createTransportZoneMembership(transportZone.getZoneName());
222 Class<? extends TunnelTypeBase> tunnelType = transportZone.getTunnelType();
223 LOG.trace("Transport Zone_name: {}", transportZone.getZoneName());
224 List<Subnets> subnetsList = transportZone.getSubnets();
225 if (subnetsList != null) {
226 for (Subnets subnet : subnetsList) {
227 IpPrefix ipPrefix = subnet.getPrefix();
228 IpAddress gatewayIP = subnet.getGatewayIp();
229 int vlanID = subnet.getVlanId();
230 LOG.trace("IpPrefix: {}, gatewayIP: {}, vlanID: {} ", ipPrefix, gatewayIP, vlanID);
231 List<Vteps> vtepsList = subnet.getVteps();
232 if (vtepsList != null && !vtepsList.isEmpty()) {
233 for (Vteps vteps : vtepsList) {
234 BigInteger dpnID = vteps.getDpnId();
235 String port = vteps.getPortname();
236 IpAddress ipAddress = vteps.getIpAddress();
237 boolean useOfTunnel = ItmUtils.falseIfNull(vteps.isOptionOfTunnel());
238 LOG.trace("DpnID: {}, port: {}, ipAddress: {}", dpnID, port, ipAddress);
239 TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(dpnID, ipAddress, port,
240 useOfTunnel, vlanID, ipPrefix, gatewayIP, zones, tunnelType);
241 List<TunnelEndPoints> tunnelEndPointsList = mapDPNToTunnelEndpt.get(dpnID);
242 if (tunnelEndPointsList != null) {
243 LOG.trace("Existing DPN info list in the Map: {} ", dpnID);
244 tunnelEndPointsList.add(tunnelEndPoints);
246 LOG.trace("Adding new DPN info list to the Map: {} ", dpnID);
247 tunnelEndPointsList = new ArrayList<>();
248 tunnelEndPointsList.add(tunnelEndPoints);
249 mapDPNToTunnelEndpt.put(dpnID, tunnelEndPointsList);
256 if (!mapDPNToTunnelEndpt.isEmpty()) {
257 Set<BigInteger> keys = mapDPNToTunnelEndpt.keySet();
258 LOG.trace("List of dpns in the Map: {} ", keys);
259 for (BigInteger key : keys) {
260 DPNTEPsInfo newDpnTepsInfo = ItmUtils.createDPNTepInfo(key, mapDPNToTunnelEndpt.get(key));
261 dpnTepInfo.add(newDpnTepsInfo);
267 private List<HwVtep> createhWVteps(TransportZone transportZone) {
268 List<HwVtep> hwVtepsList = new ArrayList<>();
270 String zoneName = transportZone.getZoneName();
271 Class<? extends TunnelTypeBase> tunnelType = transportZone.getTunnelType();
272 LOG.trace("Transport Zone_name: {}", zoneName);
273 List<Subnets> subnetsList = transportZone.getSubnets();
274 if (subnetsList != null) {
275 for (Subnets subnet : subnetsList) {
276 IpPrefix ipPrefix = subnet.getPrefix();
277 IpAddress gatewayIP = subnet.getGatewayIp();
278 int vlanID = subnet.getVlanId();
279 LOG.trace("IpPrefix: {}, gatewayIP: {}, vlanID: {} ", ipPrefix, gatewayIP, vlanID);
280 List<DeviceVteps> deviceVtepsList = subnet.getDeviceVteps();
281 if (deviceVtepsList != null) {
282 for (DeviceVteps vteps : deviceVtepsList) {
283 String topologyId = vteps.getTopologyId();
284 String nodeId = vteps.getNodeId();
285 IpAddress ipAddress = vteps.getIpAddress();
286 LOG.trace("topo-id: {}, node-id: {}, ipAddress: {}", topologyId, nodeId, ipAddress);
287 HwVtep hwVtep = ItmUtils.createHwVtepObject(topologyId, nodeId, ipAddress, ipPrefix, gatewayIP,
288 vlanID, tunnelType, transportZone);
290 if (hwVtepsList != null) {
291 LOG.trace("Existing hwVteps");
292 hwVtepsList.add(hwVtep);
294 LOG.trace("Adding new HwVtep {} info ", hwVtep.getHwIp());
295 hwVtepsList.add(hwVtep);
301 LOG.trace("returning hwvteplist {}", hwVtepsList);
305 private boolean validateTransportZoneParam(TransportZone transportZone) {
306 boolean validateParam = true;
307 ArrayList<TransportZoneValidator> tzValidatorList = new ArrayList<>();
308 tzValidatorList.add(new TransportZoneNameAllowed());
309 for(TransportZoneValidator tzValidator :tzValidatorList){
310 if(tzValidator.validate(transportZone) == ValidatorErrorCode.ERROR){
311 validateParam = false;
315 return validateParam;