itm and mdsal porting
[vpnservice.git] / itm / itm-impl / src / main / java / org / opendaylight / vpnservice / itm / confighelpers / ItmExternalTunnelAddWorker.java
1 /*
2  * Copyright (c) 2015, 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 package org.opendaylight.vpnservice.itm.confighelpers;
9
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
13
14 import com.google.common.base.Optional;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.vpnservice.itm.impl.ItmUtils;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVteps;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.Vteps;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.opendaylight.yangtools.yang.binding.*;
45 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.apache.commons.net.util.SubnetUtils;
49
50 import com.google.common.util.concurrent.FutureCallback;
51 import com.google.common.util.concurrent.ListenableFuture;
52
53 public class ItmExternalTunnelAddWorker {
54     private static final Logger logger = LoggerFactory.getLogger(ItmExternalTunnelAddWorker.class);
55
56     private static final FutureCallback<Void> DEFAULT_CALLBACK =
57             new FutureCallback<Void>() {
58                 public void onSuccess(Void result) {
59                     logger.debug("Success in Datastore operation");
60                 }
61
62                 public void onFailure(Throwable error) {
63                     logger.error("Error in Datastore operation", error);
64                 }
65
66                 ;
67             };
68
69     public static List<ListenableFuture<Void>> buildTunnelsToExternalEndPoint(DataBroker dataBroker, IdManagerService idManagerService,
70                                                                               List<DPNTEPsInfo> cfgDpnList, IpAddress extIp, Class<? extends TunnelTypeBase> tunType) {
71         List<ListenableFuture<Void>> futures = new ArrayList<>();
72         WriteTransaction t = dataBroker.newWriteOnlyTransaction();
73         if (null != cfgDpnList) {
74             for (DPNTEPsInfo teps : cfgDpnList) {
75                 // CHECK -- Assumption -- Only one End Point / Dpn for GRE/Vxlan Tunnels
76                 TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
77                 String interfaceName = firstEndPt.getInterfaceName();
78                 String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(idManagerService, interfaceName, firstEndPt.getIpAddress().getIpv4Address().getValue(), extIp.getIpv4Address().getValue());
79                 char[] subnetMaskArray = firstEndPt.getSubnetMask().getValue();
80                 String subnetMaskStr = String.valueOf(subnetMaskArray);
81                 SubnetUtils utils = new SubnetUtils(subnetMaskStr);
82                 String dcGwyIpStr = String.valueOf(extIp.getValue());
83                 IpAddress gwyIpAddress = (utils.getInfo().isInRange(dcGwyIpStr)) ? null : firstEndPt.getGwIpAddress();
84                 String ifDescription = tunType.getName();
85                 logger.debug(" Creating Trunk Interface with parameters trunk I/f Name - {}, parent I/f name - {}, source IP - {}, DC Gateway IP - {} gateway IP - {}", trunkInterfaceName, interfaceName, firstEndPt.getIpAddress(), extIp, gwyIpAddress);
86                 Interface iface = ItmUtils.buildTunnelInterface(teps.getDPNID(), trunkInterfaceName, String.format("%s %s", ifDescription, "Trunk Interface"), true, tunType, firstEndPt.getIpAddress(), extIp, gwyIpAddress, firstEndPt.getVLANID(), false,false,null);
87                 logger.debug(" Trunk Interface builder - {} ", iface);
88                 InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkInterfaceName);
89                 logger.debug(" Trunk Interface Identifier - {} ", trunkIdentifier);
90                 logger.trace(" Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface);
91                 t.merge(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, iface, true);
92                 // update external_tunnel_list ds
93                 InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
94                         ExternalTunnelList.class)
95                         .child(ExternalTunnel.class, new ExternalTunnelKey(extIp.toString(), teps.getDPNID().toString()));
96                 ExternalTunnel tnl = ItmUtils.buildExternalTunnel(teps.getDPNID().toString(), extIp.toString(), trunkInterfaceName);
97                 t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
98             }
99             futures.add(t.submit());
100         }
101         return futures;
102     }
103
104     public static List<ListenableFuture<Void>> buildTunnelsFromDpnToExternalEndPoint(DataBroker dataBroker, IdManagerService idManagerService,
105                                                                                      List<BigInteger> dpnId, IpAddress extIp, Class<? extends TunnelTypeBase> tunType) {
106         List<ListenableFuture<Void>> futures = new ArrayList<>();
107         List<DPNTEPsInfo> cfgDpnList = (dpnId == null) ? ItmUtils.getTunnelMeshInfo(dataBroker) : ItmUtils.getDPNTEPListFromDPNId(dataBroker, dpnId);
108         futures = buildTunnelsToExternalEndPoint(dataBroker, idManagerService, cfgDpnList, extIp, tunType);
109         return futures;
110     }
111
112     public static List<ListenableFuture<Void>> buildHwVtepsTunnels(DataBroker dataBroker, IdManagerService idManagerService, List<DPNTEPsInfo> cfgdDpnList, List<HwVtep> cfgdHwVteps) {
113         List<ListenableFuture<Void>> futures = new ArrayList<>();
114         WriteTransaction t = dataBroker.newWriteOnlyTransaction();
115         if (null != cfgdDpnList && !cfgdDpnList.isEmpty()) {
116             logger.trace("calling tunnels from css {}",cfgdDpnList);
117             tunnelsFromCSS(cfgdDpnList, idManagerService , futures, t , dataBroker);
118
119         }
120         if (null != cfgdHwVteps && !cfgdHwVteps.isEmpty() ) {
121             logger.trace("calling tunnels from hwTep {}",cfgdHwVteps);
122             tunnelsFromhWVtep(cfgdHwVteps, idManagerService, futures, t, dataBroker);
123         }
124
125         if ((cfgdDpnList != null && !cfgdDpnList.isEmpty()) || (cfgdHwVteps != null && !cfgdHwVteps.isEmpty()))
126             futures.add(t.submit());
127         return futures;
128     }
129
130     private static void tunnelsFromCSS(List<DPNTEPsInfo> cfgdDpnList, IdManagerService idManagerService, List<ListenableFuture<Void>> futures, WriteTransaction t, DataBroker dataBroker) {
131         for (DPNTEPsInfo dpn : cfgdDpnList) {
132             logger.trace("processing dpn {}" , dpn);
133             if (dpn.getTunnelEndPoints() != null && !dpn.getTunnelEndPoints().isEmpty())
134                 for (TunnelEndPoints tep : dpn.getTunnelEndPoints()) {
135                     InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class).child(TransportZone.class, new TransportZoneKey((tep.getTransportZone()))).build();
136                     Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker);
137                     if (tZoneOptional.isPresent()) {
138                         TransportZone tZone = tZoneOptional.get();
139                         //do we need to check tunnel type?
140                         if (tZone.getSubnets() != null && !tZone.getSubnets().isEmpty()) {
141                             for (Subnets sub : tZone.getSubnets()) {
142                                 if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
143                                     for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) {
144                                         String cssID = dpn.getDPNID().toString();
145                                         String nodeId = hwVtepDS.getNodeId();
146                                         //CSS-TOR
147                                         logger.trace("wire up {} and {}",tep, hwVtepDS);
148                                         if (!wireUp(dpn.getDPNID(), tep.getPortname(), sub.getVlanId(), tep.getIpAddress(), nodeId, hwVtepDS.getIpAddress(), tep.getSubnetMask(),
149                                                 sub.getGatewayIp(), sub.getPrefix(), tZone.getTunnelType(), idManagerService, dataBroker, futures, t))
150                                             logger.error("Unable to build tunnel {} -- {}", tep.getIpAddress(), hwVtepDS.getIpAddress());
151                                         //TOR-CSS
152                                         logger.trace("wire up {} and {}", hwVtepDS,tep);
153                                         if (!wireUp(hwVtepDS.getTopologyId(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(), cssID, tep.getIpAddress(), sub.getPrefix(),
154                                                 sub.getGatewayIp(), tep.getSubnetMask(), tZone.getTunnelType(), idManagerService, dataBroker, futures, t))
155                                             logger.error("Unable to build tunnel {} -- {}", hwVtepDS.getIpAddress(), tep.getIpAddress());
156
157                                     }
158                                 }
159                             }
160                         }
161                     }
162                 }
163         }
164     }
165
166     private static void tunnelsFromhWVtep(List<HwVtep> cfgdHwVteps, IdManagerService idManagerService, List<ListenableFuture<Void>> futures, WriteTransaction t, DataBroker dataBroker) {
167         for (HwVtep hwTep : cfgdHwVteps) {
168             InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class).child(TransportZone.class, new TransportZoneKey((hwTep.getTransportZone()))).build();
169             Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker);
170             if (tZoneOptional.isPresent()) {
171                 TransportZone tZone = tZoneOptional.get();
172                 //do we need to check tunnel type?
173                 if (tZone.getSubnets() != null && !tZone.getSubnets().isEmpty()) {
174                     for (Subnets sub : tZone.getSubnets()) {
175                         if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
176                             for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) {
177                                 if (hwVtepDS.getIpAddress().equals(hwTep.getHwIp()))
178                                     continue;//dont mesh with self
179                                 //TOR1-TOR2
180                                 logger.trace("wire up {} and {}",hwTep, hwVtepDS);
181                                 if (!wireUp(hwTep.getTopo_id(), hwTep.getNode_id(), hwTep.getHwIp(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(),
182                                         hwTep.getIpPrefix(), hwTep.getGatewayIP(), sub.getPrefix(), tZone.getTunnelType(), idManagerService, dataBroker, futures, t))
183                                     logger.error("Unable to build tunnel {} -- {}", hwTep.getHwIp(), hwVtepDS.getIpAddress());
184                                 //TOR2-TOR1
185                                 logger.trace("wire up {} and {}", hwVtepDS,hwTep);
186                                 if (!wireUp(hwTep.getTopo_id(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(), hwTep.getNode_id(), hwTep.getHwIp(),
187                                         sub.getPrefix(), sub.getGatewayIp(), hwTep.getIpPrefix(), tZone.getTunnelType(), idManagerService, dataBroker, futures, t))
188                                     logger.error("Unable to build tunnel {} -- {}", hwVtepDS.getIpAddress(), hwTep.getHwIp());
189                             }
190                         }
191                         if (sub.getVteps() != null && !sub.getVteps().isEmpty()) {
192                             for (Vteps vtep : sub.getVteps()) {
193                                 //TOR-CSS
194                                 String cssID = vtep.getDpnId().toString();
195                                 logger.trace("wire up {} and {}",hwTep, vtep);
196                                 if(!wireUp(hwTep.getTopo_id(), hwTep.getNode_id(), hwTep.getHwIp(), cssID, vtep.getIpAddress(), hwTep.getIpPrefix(),
197                                         hwTep.getGatewayIP(), sub.getPrefix(), tZone.getTunnelType(),idManagerService, dataBroker, futures, t ))
198                                     logger.error("Unable to build tunnel {} -- {}", hwTep.getHwIp(), vtep.getIpAddress());
199                                     //CSS-TOR
200                                 logger.trace("wire up {} and {}", vtep,hwTep);
201                                 if(!wireUp(vtep.getDpnId(), vtep.getPortname(), sub.getVlanId(), vtep.getIpAddress(),
202                                                 hwTep.getNode_id(),hwTep.getHwIp(),sub.getPrefix(), sub.getGatewayIp(),hwTep.getIpPrefix(),tZone.getTunnelType(),idManagerService, dataBroker, futures, t ));
203
204                             }
205
206                         }
207                     }
208                 }
209             }
210         }
211     }
212
213     //for tunnels from TOR device
214     private static boolean wireUp(String topo_id, String srcNodeid, IpAddress srcIp, String dstNodeId, IpAddress dstIp, IpPrefix srcSubnet,
215                                   IpAddress gWIp, IpPrefix dstSubnet, Class<? extends TunnelTypeBase> tunType, IdManagerService idManagerService, DataBroker dataBroker, List<ListenableFuture<Void>> futures, WriteTransaction t) {
216         IpAddress gwyIpAddress = (srcSubnet.equals(dstSubnet)) ? null : gWIp;
217         String parentIf =  ItmUtils.getHwParentIf(topo_id, srcNodeid);
218         String tunnelIfName = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf, srcIp.getIpv4Address().getValue(), dstIp.getIpv4Address().getValue());
219         logger.debug(" Creating ExternalTrunk Interface with parameters Name - {}, parent I/f name - {}, source IP - {}, destination IP - {} gateway IP - {}", tunnelIfName, parentIf, srcIp, dstIp, gwyIpAddress);
220         Interface hwTunnelIf = ItmUtils.buildHwTunnelInterface(tunnelIfName, String.format("%s %s", tunType.getName(), "Trunk Interface"),
221                 true, topo_id, srcNodeid, tunType, srcIp, dstIp, gwyIpAddress, true);
222         InstanceIdentifier<Interface> ifIID = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(tunnelIfName)).build();
223         logger.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, hwTunnelIf);
224         t.merge(LogicalDatastoreType.CONFIGURATION, ifIID, hwTunnelIf, true);
225         // also update itm-state ds?
226         InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
227                 ExternalTunnelList.class)
228                 .child(ExternalTunnel.class, new ExternalTunnelKey(getExternalTunnelKey(dstNodeId), getExternalTunnelKey(srcNodeid)));
229         ExternalTunnel tnl = ItmUtils.buildExternalTunnel(getExternalTunnelKey(srcNodeid), getExternalTunnelKey(dstNodeId), tunnelIfName);
230         t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
231         return true;
232     }
233
234     //for tunnels from CSS
235     private static boolean wireUp(BigInteger dpnId,String portname, Integer vlanId, IpAddress srcIp, String dstNodeId, IpAddress dstIp, IpPrefix srcSubnet,
236                                   IpAddress gWIp, IpPrefix dstSubnet, Class<? extends TunnelTypeBase> tunType, IdManagerService idManagerService, DataBroker dataBroker, List<ListenableFuture<Void>> futures, WriteTransaction t) {
237         IpAddress gwyIpAddress = (srcSubnet.equals(dstSubnet)) ? null : gWIp;
238         String parentIf = ItmUtils.getInterfaceName(dpnId, portname, vlanId);
239         String tunnelIfName = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf, srcIp.getIpv4Address().getValue(), dstIp.getIpv4Address().getValue());
240         logger.debug(" Creating ExternalTrunk Interface with parameters Name - {}, parent I/f name - {}, source IP - {}, destination IP - {} gateway IP - {}", tunnelIfName, parentIf, srcIp, dstIp, gwyIpAddress);
241         Interface extTunnelIf = ItmUtils.buildTunnelInterface(dpnId, tunnelIfName, String.format("%s %s", tunType.getName(), "Trunk Interface"), true, tunType, srcIp, dstIp, gwyIpAddress, vlanId, false, true, 5L);
242         InstanceIdentifier<Interface> ifIID = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(tunnelIfName)).build();
243         logger.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, extTunnelIf);
244         t.merge(LogicalDatastoreType.CONFIGURATION, ifIID, extTunnelIf, true);
245         InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
246                 ExternalTunnelList.class)
247                 .child(ExternalTunnel.class, new ExternalTunnelKey(getExternalTunnelKey(dstNodeId), dpnId.toString()));
248         ExternalTunnel tnl = ItmUtils.buildExternalTunnel(dpnId.toString(), getExternalTunnelKey(dstNodeId), tunnelIfName);
249         t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
250         return true;
251     }
252     
253     static String getExternalTunnelKey(String nodeid) {
254         if (nodeid.indexOf("physicalswitch") > 0) {
255             nodeid = nodeid.substring(0, nodeid.indexOf("physicalswitch") - 1);
256         }
257         return nodeid;
258     }
259 }
260