Add support for choosing segmentation id
[unimgr.git] / netvirt / src / main / java / org / opendaylight / unimgr / mef / netvirt / NetvirtVpnUtils.java
1 /*
2  * Copyright (c) 2016 Hewlett Packard Enterprise, Co. 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.unimgr.mef.netvirt;
10
11 import java.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.UUID;
16
17 import org.apache.commons.net.util.SubnetUtils;
18 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
21 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.genius.mdsalutil.MDSALUtil;
24 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
25 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
26 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
27 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
28 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
29 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
30 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
31 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
32 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
33 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
34 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddress;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddressBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkMaps;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetAddedToVpnBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetDeletedFromVpnBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.IpVersionV4;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
72 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
75
76 import com.google.common.base.Optional;
77
78 public class NetvirtVpnUtils {
79     private static final Logger logger = LoggerFactory.getLogger(NetvirtVpnUtils.class);
80     private final static String ELAN_PREFIX = "elan.";
81     private final static String IP_ADDR_SUFFIX = "/32";
82     private final static String IP_MUSK_SEPARATOR = "/";
83
84     public static void createVpnInstance(DataBroker dataBroker, String instanceName) {
85         WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
86         createVpnInstance(instanceName, tx);
87         MdsalUtils.commitTransaction(tx);
88     }
89
90     public static void createVpnInstance(String instanceName, WriteTransaction tx) {
91         VpnInstanceBuilder builder = new VpnInstanceBuilder();
92         builder.setVpnInstanceName(instanceName);
93         Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder();
94         VpnTargetsBuilder vpnTargetsB = new VpnTargetsBuilder();
95         vpnTargetsB.setVpnTarget(new ArrayList<VpnTarget>());
96         ipv4FamilyBuilder.setVpnTargets(vpnTargetsB.build());
97
98         // WA till netvirt will allow creation of VPN without RD
99         UUID vpnId = UUID.fromString(instanceName);
100         String rd = String.valueOf(Math.abs(vpnId.getLeastSignificantBits()));
101         ipv4FamilyBuilder.setRouteDistinguisher(rd);
102         builder.setIpv4Family(ipv4FamilyBuilder.build());
103
104         tx.put(LogicalDatastoreType.CONFIGURATION, getVpnInstanceInstanceIdentifier(instanceName), builder.build());
105     }
106
107     public static void removeVpnInstance(String instanceName, WriteTransaction tx) {
108         tx.delete(LogicalDatastoreType.CONFIGURATION, getVpnInstanceInstanceIdentifier(instanceName));
109     }
110
111     private static InstanceIdentifier<VpnInstance> getVpnInstanceInstanceIdentifier(String instanceName) {
112         return InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class, new VpnInstanceKey(instanceName))
113                 .build();
114     }
115
116     public static void createUpdateVpnInterface(DataBroker dataBroker, String vpnName, String interfaceName,
117             String ifAddr, String macAddress, boolean primary, String gwIpAddress, String directSubnetId) {
118         WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
119         createUpdateVpnInterface(vpnName, interfaceName, ifAddr, macAddress, primary, gwIpAddress, directSubnetId, tx);
120         MdsalUtils.commitTransaction(tx);
121     }
122
123     public static void createUpdateVpnInterface(String vpnName, String interfaceName, IpPrefix ifPrefix,
124             String macAddress, boolean primary, IpPrefix gwIpAddress, String directSubnetId, WriteTransaction tx) {
125         synchronized (interfaceName.intern()) {
126             String ipAddress = null;
127             String nextHopIp = null;
128             if (primary) {
129                 ipAddress = getAddressFromSubnet(ipPrefixToString(ifPrefix));
130             } else {
131                 ipAddress = ipPrefixToString(ifPrefix);
132                 nextHopIp = getIpAddressFromPrefix(ipPrefixToString(gwIpAddress));
133             }
134             createUpdateVpnInterface(vpnName, interfaceName, ipAddress, macAddress, primary, nextHopIp, directSubnetId,
135                     tx);
136         }
137     }
138
139     public static void createUpdateVpnInterface(String vpnName, String interfaceName, String ipAddress,
140             String macAddress, boolean primary, String nextHopIp, String subnetId, WriteTransaction tx) {
141         synchronized (interfaceName.intern()) {
142             Adjacencies adjancencies = buildInterfaceAdjacency(ipAddress, macAddress, primary, nextHopIp, subnetId);
143             VpnInterfaceBuilder einterfaceBuilder = createVpnInterface(vpnName, interfaceName, adjancencies);
144
145             tx.merge(LogicalDatastoreType.CONFIGURATION, getVpnInterfaceInstanceIdentifier(interfaceName),
146                     einterfaceBuilder.build());
147         }
148     }
149
150     private static VpnInterfaceBuilder createVpnInterface(String instanceName, String interfaceName,
151             Adjacencies adjacencies) {
152         VpnInterfaceBuilder einterfaceBuilder = new VpnInterfaceBuilder();
153         einterfaceBuilder.setVpnInstanceName(instanceName);
154         einterfaceBuilder.setName(interfaceName);
155         einterfaceBuilder.addAugmentation(Adjacencies.class, adjacencies);
156         return einterfaceBuilder;
157     }
158
159     private static Adjacencies buildInterfaceAdjacency(String ipAddress, String macAddress, boolean primary,
160             String nextHopIp, String subnetId) {
161         AdjacenciesBuilder builder = new AdjacenciesBuilder();
162         List<Adjacency> list = new ArrayList<>();
163
164         AdjacencyBuilder aBuilder = new AdjacencyBuilder();
165         aBuilder.setIpAddress(ipAddress);
166         if (macAddress != null) {
167             aBuilder.setMacAddress(macAddress);
168         }
169         aBuilder.setPrimaryAdjacency(primary);
170         if (subnetId != null) {
171             aBuilder.setSubnetId(new Uuid(subnetId));
172         }
173         if (nextHopIp != null) {
174             aBuilder.setNextHopIpList(Arrays.asList(nextHopIp));
175         }
176         list.add(aBuilder.build());
177
178         builder.setAdjacency(list);
179         return builder.build();
180     }
181
182     public static void removeVpnInterface(String interfaceName, WriteTransaction tx) {
183         synchronized (interfaceName.intern()) {
184             tx.delete(LogicalDatastoreType.CONFIGURATION, getVpnInterfaceInstanceIdentifier(interfaceName));
185         }
186     }
187
188     public static void removeVpnInterfaceAdjacencies(DataBroker dataBroker, String vpnName, String interfaceName) {
189         InstanceIdentifier<VpnInterface> identifier = getVpnInterfaceInstanceIdentifier(interfaceName);
190         InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
191         Optional<Adjacencies> adjacencies = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
192         List<Adjacency> adjacenciesList = adjacencies.isPresent() && adjacencies.get().getAdjacency() != null
193                 ? adjacencies.get().getAdjacency() : Collections.emptyList();
194         adjacenciesList.forEach(a -> {
195             String ipStr = getIpAddressFromPrefix(a.getIpAddress());
196             InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortIdentifier(vpnName, ipStr);
197             MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
198         });
199
200         AdjacenciesBuilder builder = new AdjacenciesBuilder();
201         List<Adjacency> list = new ArrayList<>();
202         builder.setAdjacency(list);
203         VpnInterfaceBuilder einterfaceBuilder = createVpnInterface(vpnName, interfaceName, builder.build());
204
205         MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
206                 getVpnInterfaceInstanceIdentifier(interfaceName), einterfaceBuilder.build());
207
208     }
209
210     public static void removeVpnInterfaceAdjacency(DataBroker dataBroker, String interfaceName, IpPrefix ifPrefix) {
211         WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
212         String ipAddress = ipPrefixToString(ifPrefix);
213         removeVpnInterfaceAdjacency(interfaceName, ipAddress, tx);
214         MdsalUtils.commitTransaction(tx);
215     }
216
217     public static void removeVpnInterfaceAdjacency(DataBroker dataBroker, String interfaceName, IpAddress ifAddress) {
218         WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
219         String ifAddressStr = getAddressFromSubnet(ipAddressToString(ifAddress));
220         removeVpnInterfaceAdjacency(interfaceName, ifAddressStr, tx);
221         MdsalUtils.commitTransaction(tx);
222     }
223
224     private static void removeVpnInterfaceAdjacency(String interfaceName, String ipAddress, WriteTransaction tx) {
225         synchronized (interfaceName.intern()) {
226
227             InstanceIdentifier<Adjacency> adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class)
228                     .child(VpnInterface.class, new VpnInterfaceKey(interfaceName)).augmentation(Adjacencies.class)
229                     .child(Adjacency.class, new AdjacencyKey(ipAddress)).build();
230
231             tx.delete(LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
232         }
233     }
234
235     private static InstanceIdentifier<VpnInterface> getVpnInterfaceInstanceIdentifier(String interfaceName) {
236         return InstanceIdentifier.builder(VpnInterfaces.class)
237                 .child(VpnInterface.class, new VpnInterfaceKey(interfaceName)).build();
238     }
239
240     public static void createVpnPortFixedIp(DataBroker dataBroker, String vpnName, String portName, IpPrefix ipAddress,
241             MacAddress macAddress) {
242         String fixedIpPrefix = ipPrefixToString(ipAddress);
243         String fixedIp = getIpAddressFromPrefix(fixedIpPrefix);
244
245         WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
246         createVpnPortFixedIp(vpnName, portName, fixedIp, macAddress, tx);
247         MdsalUtils.commitTransaction(tx);
248     }
249
250     public static void createVpnPortFixedIp(String vpnName, String portName, IpPrefix ipAddress, MacAddress macAddress,
251             WriteTransaction tx) {
252         String fixedIpPrefix = ipPrefixToString(ipAddress);
253         String fixedIp = getIpAddressFromPrefix(fixedIpPrefix);
254         createVpnPortFixedIp(vpnName, portName, fixedIp, macAddress, tx);
255     }
256
257     private static void createVpnPortFixedIp(String vpnName, String portName, String fixedIp, MacAddress macAddress,
258             WriteTransaction tx) {
259         synchronized ((vpnName + fixedIp).intern()) {
260             InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortIdentifier(vpnName, fixedIp);
261             VpnPortipToPortBuilder builder = new VpnPortipToPortBuilder()
262                     .setKey(new VpnPortipToPortKey(fixedIp, vpnName)).setVpnName(vpnName).setPortFixedip(fixedIp)
263                     .setPortName(portName).setMacAddress(macAddress.getValue()).setSubnetIp(true);
264             tx.put(LogicalDatastoreType.OPERATIONAL, id, builder.build());
265             logger.debug(
266                     "Interface to fixedIp added: {}, vpn {}, interface {}, mac {} added to " + "VpnPortipToPort DS",
267                     fixedIp, vpnName, portName, macAddress);
268         }
269     }
270
271     public static VpnPortipToPort getVpnPortFixedIp(DataBroker dataBroker, String vpnName, String fixedIp) {
272         InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortIdentifier(vpnName, fixedIp);
273         Optional<VpnPortipToPort> opt = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
274         return opt != null && opt.isPresent() ? opt.get() : null;
275     }
276
277     public static void removeVpnPortFixedIp(String vpnName, IpPrefix ipAddress, WriteTransaction tx) {
278         String fixedIpPrefix = ipPrefixToString(ipAddress);
279         String fixedIp = getIpAddressFromPrefix(fixedIpPrefix);
280         InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortIdentifier(vpnName, fixedIp);
281         tx.delete(LogicalDatastoreType.OPERATIONAL, id);
282     }
283
284     public static void registerDirectSubnetForVpn(DataBroker dataBroker, Uuid subnetName, IpAddress gwIpAddress) {
285         final SubnetKey subnetkey = new SubnetKey(subnetName);
286
287         final InstanceIdentifier<Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class)
288                 .child(Subnets.class).child(Subnet.class, subnetkey);
289
290         SubnetBuilder subnetBuilder = new SubnetBuilder();
291         subnetBuilder.setIpVersion(IpVersionV4.class);
292         subnetBuilder.setGatewayIp(gwIpAddress);
293         subnetBuilder.setKey(subnetkey);
294         MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetidentifier, subnetBuilder.build());
295     }
296
297     public static void unregisterDirectSubnetForVpn(DataBroker dataBroker, Uuid subnetName) {
298         final SubnetKey subnetkey = new SubnetKey(subnetName);
299         final InstanceIdentifier<Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class)
300                 .child(Subnets.class).child(Subnet.class, subnetkey);
301
302         MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetidentifier);
303     }
304
305     public static void addDirectSubnetToVpn(DataBroker dataBroker,
306             final NotificationPublishService notificationPublishService, String vpnName, String subnetName,
307             IpPrefix subnetIpPrefix, String interfaceName, int waitForElan) {
308         InstanceIdentifier<ElanInstance> elanIdentifierId = NetvirtUtils.getElanInstanceInstanceIdentifier(subnetName);
309
310         @SuppressWarnings("resource") // AutoCloseable
311         DataWaitListener<ElanInstance> elanTagWaiter = new DataWaitListener<>(
312                 dataBroker, elanIdentifierId, 10, LogicalDatastoreType.CONFIGURATION, el -> el.getElanTag());
313         if ( !elanTagWaiter.waitForData()) {
314             logger.error("Trying to add invalid elan {} to vpn {}", subnetName, vpnName);
315             return;
316         }
317
318         Uuid subnetId = new Uuid(subnetName);
319         logger.info("Adding subnet {} {} to elan map", subnetId, subnetId);
320         createSubnetToNetworkMapping(dataBroker, subnetId, subnetId);
321
322         String subnetIp = getSubnetFromPrefix(ipPrefixToString(subnetIpPrefix));
323         logger.info("Adding subnet {} {} to vpn {}", subnetName, subnetIp, vpnName);
324         updateSubnetNode(dataBroker, new Uuid(vpnName), subnetId, subnetIp);
325
326         logger.info("Adding port {} to subnet {}", interfaceName, subnetName);
327         updateSubnetmapNodeWithPorts(dataBroker, subnetId, new Uuid(interfaceName), null);
328
329         Optional<ElanInstance> elanInstance = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
330                 elanIdentifierId);
331         Long elanTag = elanInstance.get().getElanTag();
332
333         logger.info("Publish subnet {}", subnetName);
334         publishSubnetAddNotification(notificationPublishService, subnetId, subnetIp, vpnName, elanTag);
335         logger.info("Finished Working on subnet {}", subnetName);
336     }
337
338     public static void removeDirectSubnetFromVpn(DataBroker dataBroker,
339             final NotificationPublishService notificationPublishService, String vpnName, String subnetName,
340             String interfaceName) {
341         InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class)
342                 .child(ElanInstance.class, new ElanInstanceKey(subnetName)).build();
343         Optional<ElanInstance> elanInstance = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
344                 elanIdentifierId);
345         if (!elanInstance.isPresent()) {
346             logger.error("Trying to add invalid elan {} to vpn {}", subnetName, vpnName);
347             return;
348         }
349         Long elanTag = elanInstance.get().getElanTag() != null ? elanInstance.get().getElanTag()
350                 : elanInstance.get().getSegmentationId();
351         Uuid subnetId = new Uuid(subnetName);
352
353         logger.info("Publish subnet remove {}", subnetName);
354         publishSubnetRemoveNotification(notificationPublishService, subnetId, vpnName, elanTag);
355
356         logger.info("Removing port {} from subnet {}", interfaceName, subnetName);
357         updateSubnetmapNodeWithPorts(dataBroker, subnetId, null, new Uuid(interfaceName));
358
359         logger.info("Removing subnet {} from vpn {}", subnetName, vpnName);
360         removeSubnetNode(dataBroker, new Uuid(vpnName));
361
362         logger.info("Removing subnet {} to elan map", subnetId);
363         removeSubnetToNetworkMapping(dataBroker, subnetId);
364
365         logger.info("Finished Working on subnet {}", subnetName);
366     }
367
368     private static void createSubnetToNetworkMapping(DataBroker dataBroker, Uuid subnetId, Uuid networkId) {
369         InstanceIdentifier<NetworkMap> networkMapIdentifier = getNetworkMapIdentifier(networkId);
370         Optional<NetworkMap> optionalNetworkMap = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
371                 networkMapIdentifier);
372         NetworkMapBuilder nwMapBuilder = null;
373         if (optionalNetworkMap.isPresent()) {
374             nwMapBuilder = new NetworkMapBuilder(optionalNetworkMap.get());
375         } else {
376             nwMapBuilder = new NetworkMapBuilder().setKey(new NetworkMapKey(networkId)).setNetworkId(networkId);
377             logger.debug("Adding a new network node in NetworkMaps DS for network {}", networkId.getValue());
378         }
379         List<Uuid> subnetIdList = nwMapBuilder.getSubnetIdList();
380         if (subnetIdList == null) {
381             subnetIdList = new ArrayList<>();
382         }
383         subnetIdList.add(subnetId);
384         nwMapBuilder.setSubnetIdList(subnetIdList);
385         MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier, nwMapBuilder.build());
386         logger.debug("Created subnet-network mapping for subnet {} network {}", subnetId.getValue(),
387                 networkId.getValue());
388     }
389
390     private static void removeSubnetToNetworkMapping(DataBroker dataBroker, Uuid networkId) {
391         InstanceIdentifier<NetworkMap> networkMapIdentifier = getNetworkMapIdentifier(networkId);
392         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier);
393         logger.debug("Deleted subnet-network mapping for  network {}", networkId.getValue());
394     }
395
396     protected static void updateSubnetNode(DataBroker dataBroker, Uuid vpnId, Uuid subnetId, String subnetIp) {
397         Subnetmap subnetmap = null;
398         SubnetmapBuilder builder = null;
399         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
400                 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
401
402         synchronized (subnetId.getValue().intern()) {
403             Optional<Subnetmap> sn = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
404             if (sn.isPresent()) {
405                 builder = new SubnetmapBuilder(sn.get());
406                 logger.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
407             } else {
408                 builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
409                 logger.debug("creating new subnetmap node for subnet ID {}", subnetId.getValue());
410             }
411
412             builder.setSubnetIp(subnetIp);
413             builder.setNetworkId(subnetId);
414             builder.setVpnId(vpnId);
415
416             subnetmap = builder.build();
417             logger.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
418             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
419         }
420     }
421
422     protected static void removeSubnetNode(DataBroker dataBroker, Uuid subnetId) {
423         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
424                 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
425
426         synchronized (subnetId.getValue().intern()) {
427             logger.debug("Deleting subnetMap node: {} ", subnetId.getValue());
428             MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
429         }
430     }
431
432     private static void updateSubnetmapNodeWithPorts(DataBroker dataBroker, Uuid subnetId, Uuid portIdToAdd,
433             Uuid portIdToRemove) {
434         Subnetmap subnetmap = null;
435         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
436                 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
437         synchronized (subnetId.getValue().intern()) {
438             Optional<Subnetmap> sn = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
439             if (sn.isPresent()) {
440                 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
441                 if (null != portIdToAdd) {
442                     List<Uuid> portList = builder.getPortList();
443                     if (null == portList) {
444                         portList = new ArrayList<>();
445                     }
446                     if (portIdToAdd != null) {
447                         portList.add(portIdToAdd);
448                         logger.debug("Updating subnetmap node {} with port {}", subnetId.getValue(),
449                                 portIdToAdd.getValue());
450
451                     }
452                     if (portIdToRemove != null) {
453                         portList.remove(portIdToRemove);
454                         logger.debug("Updating subnetmap node {} removing port {}", subnetId.getValue(),
455                                 portIdToRemove.getValue());
456
457                     }
458                     builder.setPortList(portList);
459                 }
460                 subnetmap = builder.build();
461                 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
462             } else {
463                 logger.error("Trying to update non-existing subnetmap node {} ", subnetId.getValue());
464             }
465         }
466     }
467
468     private static InstanceIdentifier<NetworkMap> getNetworkMapIdentifier(Uuid networkId) {
469         InstanceIdentifier<NetworkMap> id = InstanceIdentifier.builder(NetworkMaps.class)
470                 .child(NetworkMap.class, new NetworkMapKey(networkId)).build();
471         return id;
472     }
473
474     private static InstanceIdentifier<VpnPortipToPort> getVpnPortipToPortIdentifier(String vpnName, String fixedIp) {
475         InstanceIdentifier<VpnPortipToPort> id = InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
476                 .child(VpnPortipToPort.class, new VpnPortipToPortKey(fixedIp, vpnName)).build();
477         return id;
478     }
479
480     public static InstanceIdentifier<VpnPortipToPort> getVpnPortipToPortIdentifier() {
481         return InstanceIdentifier.builder(NeutronVpnPortipPortData.class).child(VpnPortipToPort.class).build();
482     }
483
484     private static void publishSubnetAddNotification(final NotificationPublishService notificationPublishService,
485             Uuid subnetId, String subnetIp, String vpnName, Long elanTag) {
486         SubnetAddedToVpnBuilder builder = new SubnetAddedToVpnBuilder();
487
488         logger.info("publish notification called for network creation");
489
490         builder.setSubnetId(subnetId);
491         builder.setSubnetIp(subnetIp);
492         builder.setVpnName(vpnName);
493         builder.setExternalVpn(true);
494         builder.setElanTag(elanTag);
495
496         try {
497             notificationPublishService.putNotification(builder.build());
498         } catch (InterruptedException e) {
499             logger.error("Fail to publish notification {}", builder, e);
500             throw new RuntimeException(e.getMessage());
501         }
502     }
503
504     private static void publishSubnetRemoveNotification(final NotificationPublishService notificationPublishService,
505             Uuid subnetId, String vpnName, Long elanTag) {
506         SubnetDeletedFromVpnBuilder builder = new SubnetDeletedFromVpnBuilder();
507
508         logger.info("publish notification called for network deletion");
509
510         builder.setSubnetId(subnetId);
511         builder.setVpnName(vpnName);
512         builder.setExternalVpn(true);
513         builder.setElanTag(elanTag);
514
515         try {
516             notificationPublishService.putNotification(builder.build());
517         } catch (InterruptedException e) {
518             logger.error("Fail to publish notification {}", builder, e);
519             throw new RuntimeException(e.getMessage());
520         }
521     }
522
523     public static void sendArpRequest(OdlArputilService arpUtilService, IpAddress srcIpAddress, IpAddress dstIpAddress,
524             String interf) {
525         try {
526             List<InterfaceAddress> interfaceAddresses = new ArrayList<>();
527             interfaceAddresses
528                     .add(new InterfaceAddressBuilder().setInterface(interf).setIpAddress(srcIpAddress).build());
529
530             SendArpRequestInput sendArpRequestInput = new SendArpRequestInputBuilder().setIpaddress(dstIpAddress)
531                     .setInterfaceAddress(interfaceAddresses).build();
532             arpUtilService.sendArpRequest(sendArpRequestInput);
533         } catch (Exception e) {
534             logger.error("Failed to send ARP request to IP {} from interfaces {}",
535                     dstIpAddress.getIpv4Address().getValue(), interf, e);
536             throw new RuntimeException(e.getMessage());
537         }
538     }
539
540     public static String getElanNameForVpnPort(String uniId, String ipUniId) {
541         return getUUidFromString(ELAN_PREFIX + uniId + ipUniId);
542     }
543
544     public static String getIpAddressFromPrefix(String prefix) {
545         return prefix.split(IP_MUSK_SEPARATOR)[0];
546     }
547
548     private static String getMaskFromPrefix(String prefix) {
549         return prefix.split(IP_MUSK_SEPARATOR)[1];
550     }
551
552     public static String getSubnetFromPrefix(String prefix) {
553         SubnetInfo subnet = new SubnetUtils(prefix).getInfo();
554         return subnet.getNetworkAddress() + IP_MUSK_SEPARATOR + getMaskFromPrefix(prefix);
555     }
556
557     public static String getSubnetFromPrefix(IpPrefix prefix) {
558         String prefixStr = ipPrefixToString(prefix);
559         return getSubnetFromPrefix(prefixStr);
560     }
561
562     private static String getAddressFromSubnet(String prefix) {
563         String myAddress = getIpAddressFromPrefix(prefix);
564         return myAddress + IP_ADDR_SUFFIX;
565     }
566
567     public static String getUUidFromString(String key) {
568         return java.util.UUID.nameUUIDFromBytes(key.getBytes()).toString();
569     }
570
571     public static String ipPrefixToString(IpPrefix ipAddress) {
572         if (ipAddress.getIpv4Prefix() != null) {
573             return ipAddress.getIpv4Prefix().getValue();
574         }
575
576         return ipAddress.getIpv6Prefix().getValue();
577     }
578
579     public static String ipAddressToString(IpAddress ipAddress) {
580         if (ipAddress.getIpv4Address() != null) {
581             return ipAddress.getIpv4Address().getValue();
582         }
583
584         return ipAddress.getIpv6Address().getValue();
585     }
586 }