Blueprint XML Config support in ITM.
[genius.git] / itm / itm-impl / src / main / java / org / opendaylight / genius / itm / listeners / TransportZoneListener.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.genius.itm.listeners;
10
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;
17 import java.util.Map;
18 import java.util.Set;
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.globals.ITMConstants;
34 import org.opendaylight.genius.itm.impl.ITMManager;
35 import org.opendaylight.genius.itm.impl.ItmUtils;
36 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZonesBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVteps;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
52 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 /**
57  * This class listens for interface creation/removal/update in Configuration DS.
58  * This is used to handle interfaces for base of-ports.
59  */
60 @Singleton
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;
68     private final ItmConfig itmConfig;
69
70     @Inject
71     public TransportZoneListener(final DataBroker dataBroker, final IdManagerService idManagerService,
72                                  final IMdsalApiManager iMdsalApiManager,final ITMManager itmManager,
73                                  final ItmConfig itmConfig) {
74         super(TransportZone.class, TransportZoneListener.class);
75         this.dataBroker = dataBroker;
76         this.idManagerService = idManagerService;
77         initializeTZNode(dataBroker);
78         this.itmManager = itmManager;
79         this.mdsalManager = iMdsalApiManager;
80         this.itmConfig = itmConfig;
81     }
82
83     @PostConstruct
84     public void start() {
85         registerListener(LogicalDatastoreType.CONFIGURATION, this.dataBroker);
86         LOG.info("tzChangeListener Started");
87     }
88
89     @Override
90     @PreDestroy
91     public void close() {
92         LOG.info("tzChangeListener Closed");
93     }
94
95     private void initializeTZNode(DataBroker db) {
96         ReadWriteTransaction transaction = db.newReadWriteTransaction();
97         InstanceIdentifier<TransportZones> path = InstanceIdentifier.create(TransportZones.class);
98         CheckedFuture<Optional<TransportZones>, ReadFailedException> tzones = transaction
99                 .read(LogicalDatastoreType.CONFIGURATION, path);
100         try {
101             if (!tzones.get().isPresent()) {
102                 TransportZonesBuilder tzb = new TransportZonesBuilder();
103                 transaction.put(LogicalDatastoreType.CONFIGURATION, path, tzb.build());
104                 transaction.submit();
105             } else {
106                 transaction.cancel();
107             }
108         } catch (Exception e) {
109             LOG.error("Error initializing TransportZones {}", e);
110         }
111     }
112
113     @Override
114     protected InstanceIdentifier<TransportZone> getWildCardPath() {
115         return InstanceIdentifier.create(TransportZones.class).child(TransportZone.class);
116     }
117
118     @Override
119     protected TransportZoneListener getDataTreeChangeListener() {
120         return TransportZoneListener.this;
121     }
122
123     @Override
124     protected void remove(InstanceIdentifier<TransportZone> key, TransportZone tzOld) {
125         LOG.debug("Received Transport Zone Remove Event: {}, {}", key, tzOld);
126
127         boolean allowTunnelDeletion = false;
128
129         // check if TZ received for removal is default-transport-zone,
130         // if yes, then check if it is received from northbound, then
131         // do not entertain request and skip tunnels remove operation
132         // if def-tz removal request is due to def-tz-enabled flag is disabled or
133         // due to change in def-tz-tunnel-type, then allow def-tz tunnels deletion
134         if (tzOld.getZoneName().equalsIgnoreCase(ITMConstants.DEFAULT_TRANSPORT_ZONE)) {
135             // Get TunnelTypeBase object for tunnel-type configured in config file
136             Class<? extends TunnelTypeBase> tunType = ItmUtils.getTunnelType(itmConfig.getDefTzTunnelType());
137
138             if ((!itmConfig.isDefTzEnabled()) || (!tzOld.getTunnelType().equals(tunType))) {
139                 allowTunnelDeletion = true;
140             } else {
141                 // this is case when def-tz removal request is from Northbound.
142                 allowTunnelDeletion = false;
143                 LOG.error("Deletion of {} is an incorrect usage",ITMConstants.DEFAULT_TRANSPORT_ZONE);
144             }
145         } else {
146             allowTunnelDeletion = true;
147         }
148
149         if (allowTunnelDeletion) {
150             //TODO : DPList code can be refactor with new specific class
151             // which implement TransportZoneValidator
152             List<DPNTEPsInfo> opDpnList = createDPNTepInfo(tzOld);
153             List<HwVtep> hwVtepList = createhWVteps(tzOld);
154             LOG.trace("Delete: Invoking deleteTunnels in ItmManager with DpnList {}", opDpnList);
155             if(!opDpnList.isEmpty() || !hwVtepList.isEmpty()) {
156                 LOG.trace("Delete: Invoking ItmManager with hwVtep List {} " , hwVtepList);
157                 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
158                 ItmTepRemoveWorker removeWorker =
159                         new ItmTepRemoveWorker(opDpnList, hwVtepList, tzOld, dataBroker, idManagerService, mdsalManager);
160                 coordinator.enqueueJob(tzOld.getZoneName(), removeWorker);
161             }
162         }
163     }
164
165     @Override
166     protected void update(InstanceIdentifier<TransportZone> key, TransportZone tzOld, TransportZone tzNew) {
167         LOG.debug("Received Transport Zone Update Event: Key - {}, Old - {}, Updated - {}", key, tzOld, tzNew);
168         List<DPNTEPsInfo> oldDpnTepsList = createDPNTepInfo(tzOld);
169         List<DPNTEPsInfo> newDpnTepsList = createDPNTepInfo(tzNew);
170         List<DPNTEPsInfo> oldDpnTepsListcopy = new ArrayList<>();
171         oldDpnTepsListcopy.addAll(oldDpnTepsList);
172         LOG.trace("oldcopy0" + oldDpnTepsListcopy);
173         List<DPNTEPsInfo> newDpnTepsListcopy = new ArrayList<>();
174         newDpnTepsListcopy.addAll(newDpnTepsList);
175         LOG.trace("newcopy0" + newDpnTepsListcopy);
176         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
177
178         oldDpnTepsList.removeAll(newDpnTepsListcopy);
179         newDpnTepsList.removeAll(oldDpnTepsListcopy);
180
181         LOG.trace("oldDpnTepsList" + oldDpnTepsList);
182         LOG.trace("newDpnTepsList" + newDpnTepsList);
183         LOG.trace("oldcopy" + oldDpnTepsListcopy);
184         LOG.trace("newcopy" + newDpnTepsListcopy);
185         LOG.trace("oldcopy Size " + oldDpnTepsList.size());
186         LOG.trace("newcopy Size " + newDpnTepsList.size());
187         if (!newDpnTepsList.isEmpty()) {
188             LOG.trace("Adding TEPs ");
189             ItmTepAddWorker addWorker = new ItmTepAddWorker(newDpnTepsList, Collections.emptyList(), dataBroker,
190                     idManagerService, mdsalManager);
191             coordinator.enqueueJob(tzNew.getZoneName(), addWorker);
192         }
193         if (!oldDpnTepsList.isEmpty()) {
194             LOG.trace("Removing TEPs ");
195             ItmTepRemoveWorker removeWorker = new ItmTepRemoveWorker(oldDpnTepsList, Collections.emptyList(),
196                     tzOld, dataBroker, idManagerService, mdsalManager);
197             coordinator.enqueueJob(tzNew.getZoneName(), removeWorker);
198         }
199         List<HwVtep> oldHwList = createhWVteps(tzOld);
200         List<HwVtep> newHwList = createhWVteps(tzNew);
201         List<HwVtep> oldHwListcopy = new ArrayList<>();
202         oldHwListcopy.addAll(oldHwList);
203         LOG.trace("oldHwListcopy0" + oldHwListcopy);
204         List<HwVtep> newHwListcopy = new ArrayList<>();
205         newHwListcopy.addAll(newHwList);
206         LOG.trace("newHwListcopy0" + newHwListcopy);
207
208         oldHwList.removeAll(newHwListcopy);
209         newHwList.removeAll(oldHwListcopy);
210         LOG.trace("oldHwList" + oldHwList);
211         LOG.trace("newHwList" + newHwList);
212         LOG.trace("oldHwListcopy" + oldHwListcopy);
213         LOG.trace("newHwListcopy" + newHwListcopy);
214         if (!newHwList.isEmpty()) {
215             LOG.trace("Adding HW TEPs ");
216             ItmTepAddWorker addWorker = new ItmTepAddWorker(Collections.emptyList(), newHwList, dataBroker,
217                     idManagerService, mdsalManager);
218             coordinator.enqueueJob(tzNew.getZoneName(), addWorker);
219         }
220         if (!oldHwList.isEmpty()) {
221             LOG.trace("Removing HW TEPs ");
222             ItmTepRemoveWorker removeWorker = new ItmTepRemoveWorker(Collections.emptyList(), oldHwList,
223                     tzOld, dataBroker, idManagerService, mdsalManager);
224             coordinator.enqueueJob(tzNew.getZoneName(), removeWorker);
225         }
226     }
227
228     @Override
229     protected void add(InstanceIdentifier<TransportZone> key, TransportZone tzNew) {
230         LOG.debug("Received Transport Zone Add Event: {}, {}", key, tzNew);
231         List<DPNTEPsInfo> opDpnList = createDPNTepInfo(tzNew);
232         List<HwVtep> hwVtepList = createhWVteps(tzNew);
233         LOG.trace("Add: Operational dpnTepInfo - Before invoking ItmManager {}", opDpnList);
234         if (!opDpnList.isEmpty() || !hwVtepList.isEmpty()) {
235             LOG.trace("Add: Invoking ItmManager with DPN List {} ", opDpnList);
236             LOG.trace("Add: Invoking ItmManager with hwVtep List {} ", hwVtepList);
237             DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
238             ItmTepAddWorker addWorker = new ItmTepAddWorker(opDpnList, hwVtepList, dataBroker, idManagerService,
239                     mdsalManager);
240             coordinator.enqueueJob(tzNew.getZoneName(), addWorker);
241         }
242     }
243
244     private List<DPNTEPsInfo> createDPNTepInfo(TransportZone transportZone) {
245         Map<BigInteger, List<TunnelEndPoints>> mapDPNToTunnelEndpt = new ConcurrentHashMap<>();
246         List<DPNTEPsInfo> dpnTepInfo = new ArrayList<>();
247         List<TzMembership> zones = ItmUtils.createTransportZoneMembership(transportZone.getZoneName());
248         Class<? extends TunnelTypeBase> tunnelType = transportZone.getTunnelType();
249         LOG.trace("Transport Zone_name: {}", transportZone.getZoneName());
250         List<Subnets> subnetsList = transportZone.getSubnets();
251         if (subnetsList != null) {
252             for (Subnets subnet : subnetsList) {
253                 IpPrefix ipPrefix = subnet.getPrefix();
254                 IpAddress gatewayIP = subnet.getGatewayIp();
255                 int vlanID = subnet.getVlanId();
256                 LOG.trace("IpPrefix: {}, gatewayIP: {}, vlanID: {} ", ipPrefix, gatewayIP, vlanID);
257                 List<Vteps> vtepsList = subnet.getVteps();
258                 if (vtepsList != null && !vtepsList.isEmpty()) {
259                     for (Vteps vteps : vtepsList) {
260                         BigInteger dpnID = vteps.getDpnId();
261                         String port = vteps.getPortname();
262                         IpAddress ipAddress = vteps.getIpAddress();
263                         boolean useOfTunnel = ItmUtils.falseIfNull(vteps.isOptionOfTunnel());
264                         LOG.trace("DpnID: {}, port: {}, ipAddress: {}", dpnID, port, ipAddress);
265                         TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(dpnID, ipAddress, port,
266                             useOfTunnel, vlanID,  ipPrefix, gatewayIP, zones, tunnelType);
267                         List<TunnelEndPoints> tunnelEndPointsList = mapDPNToTunnelEndpt.get(dpnID);
268                         if (tunnelEndPointsList != null) {
269                             LOG.trace("Existing DPN info list in the Map: {} ", dpnID);
270                             tunnelEndPointsList.add(tunnelEndPoints);
271                         } else {
272                             LOG.trace("Adding new DPN info list to the Map: {} ", dpnID);
273                             tunnelEndPointsList = new ArrayList<>();
274                             tunnelEndPointsList.add(tunnelEndPoints);
275                             mapDPNToTunnelEndpt.put(dpnID, tunnelEndPointsList);
276                         }
277                     }
278                 }
279             }
280         }
281
282         if (!mapDPNToTunnelEndpt.isEmpty()) {
283             Set<BigInteger> keys = mapDPNToTunnelEndpt.keySet();
284             LOG.trace("List of dpns in the Map: {} ", keys);
285             for (BigInteger key : keys) {
286                 DPNTEPsInfo newDpnTepsInfo = ItmUtils.createDPNTepInfo(key, mapDPNToTunnelEndpt.get(key));
287                 dpnTepInfo.add(newDpnTepsInfo);
288             }
289         }
290         return dpnTepInfo;
291     }
292
293     private List<HwVtep> createhWVteps(TransportZone transportZone) {
294         List<HwVtep> hwVtepsList = new ArrayList<>();
295
296         String zoneName = transportZone.getZoneName();
297         Class<? extends TunnelTypeBase> tunnelType = transportZone.getTunnelType();
298         LOG.trace("Transport Zone_name: {}", zoneName);
299         List<Subnets> subnetsList = transportZone.getSubnets();
300         if (subnetsList != null) {
301             for (Subnets subnet : subnetsList) {
302                 IpPrefix ipPrefix = subnet.getPrefix();
303                 IpAddress gatewayIP = subnet.getGatewayIp();
304                 int vlanID = subnet.getVlanId();
305                 LOG.trace("IpPrefix: {}, gatewayIP: {}, vlanID: {} ", ipPrefix, gatewayIP, vlanID);
306                 List<DeviceVteps> deviceVtepsList = subnet.getDeviceVteps();
307                 if (deviceVtepsList != null) {
308                     for (DeviceVteps vteps : deviceVtepsList) {
309                         String topologyId = vteps.getTopologyId();
310                         String nodeId = vteps.getNodeId();
311                         IpAddress ipAddress = vteps.getIpAddress();
312                         LOG.trace("topo-id: {}, node-id: {}, ipAddress: {}", topologyId, nodeId, ipAddress);
313                         HwVtep hwVtep = ItmUtils.createHwVtepObject(topologyId, nodeId, ipAddress, ipPrefix, gatewayIP,
314                                 vlanID, tunnelType, transportZone);
315
316                         if (hwVtepsList != null) {
317                             LOG.trace("Existing hwVteps");
318                             hwVtepsList.add(hwVtep);
319                         } else {
320                             LOG.trace("Adding new HwVtep {} info ", hwVtep.getHwIp());
321                             hwVtepsList.add(hwVtep);
322                         }
323                     }
324                 }
325             }
326         }
327         LOG.trace("returning hwvteplist {}", hwVtepsList);
328         return hwVtepsList;
329     }
330 }