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