Neutron Port allocation for DHCP Service
[netvirt.git] / vpnservice / dhcpservice / dhcpservice-impl / src / main / java / org / opendaylight / netvirt / dhcpservice / jobs / DhcpInterfaceRemoveJob.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 package org.opendaylight.netvirt.dhcpservice.jobs;
9
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.concurrent.Callable;
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
21 import org.opendaylight.genius.mdsalutil.MDSALDataStoreUtils;
22 import org.opendaylight.genius.mdsalutil.MDSALUtil;
23 import org.opendaylight.netvirt.dhcpservice.DhcpExternalTunnelManager;
24 import org.opendaylight.netvirt.dhcpservice.DhcpManager;
25 import org.opendaylight.netvirt.dhcpservice.DhcpServiceUtils;
26 import org.opendaylight.netvirt.elan.arp.responder.ArpResponderInput;
27 import org.opendaylight.netvirt.elanmanager.api.IElanService;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710.InterfaceNameMacAddresses;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddress;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddressKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710.subnet.dhcp.port.data.SubnetToDhcpPort;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 public class DhcpInterfaceRemoveJob implements Callable<List<ListenableFuture<Void>>> {
41
42     private static final Logger LOG = LoggerFactory.getLogger(DhcpInterfaceRemoveJob.class);
43     DhcpManager dhcpManager;
44     DhcpExternalTunnelManager dhcpExternalTunnelManager;
45     DataBroker dataBroker;
46     Interface interfaceDel;
47     BigInteger dpnId;
48     IInterfaceManager interfaceManager;
49     private final IElanService elanService;
50     private static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
51         @Override
52         public void onSuccess(Void result) {
53             LOG.debug("Success in Datastore write operation");
54         }
55
56         @Override
57         public void onFailure(Throwable error) {
58             LOG.error("Error in Datastore write operation", error);
59         }
60     };
61
62     public DhcpInterfaceRemoveJob(DhcpManager dhcpManager, DhcpExternalTunnelManager dhcpExternalTunnelManager,
63                                   DataBroker dataBroker,
64                                   Interface interfaceDel, BigInteger dpnId, IInterfaceManager interfaceManager,
65                                   IElanService elanService) {
66         super();
67         this.dhcpManager = dhcpManager;
68         this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
69         this.dataBroker = dataBroker;
70         this.interfaceDel = interfaceDel;
71         this.dpnId = dpnId;
72         this.interfaceManager = interfaceManager;
73         this.elanService = elanService;
74     }
75
76     @Override
77     public List<ListenableFuture<Void>> call() throws Exception {
78         List<ListenableFuture<Void>> futures = new ArrayList<>();
79         String interfaceName = interfaceDel.getName();
80         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
81                 interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName);
82         if (iface != null) {
83             IfTunnel tunnelInterface = iface.getAugmentation(IfTunnel.class);
84             if (tunnelInterface != null && !tunnelInterface.isInternal()) {
85                 IpAddress tunnelIp = tunnelInterface.getTunnelDestination();
86                 List<BigInteger> dpns = DhcpServiceUtils.getListOfDpns(dataBroker);
87                 if (dpns.contains(dpnId)) {
88                     dhcpExternalTunnelManager.handleTunnelStateDown(tunnelIp, dpnId, futures);
89                 }
90                 return futures;
91             }
92         }
93         Port port = dhcpManager.getNeutronPort(interfaceName);
94         java.util.Optional<String> subnetId = DhcpServiceUtils.getNeutronSubnetId(port);
95         if (subnetId.isPresent()) {
96             java.util.Optional<SubnetToDhcpPort> subnetToDhcp = DhcpServiceUtils.getSubnetDhcpPortData(dataBroker,
97                     subnetId.get());
98             if (subnetToDhcp.isPresent()) {
99                 LOG.trace("Removing ArpResponder flow for last interface {} on DPN {}", interfaceName, dpnId);
100                 ArpResponderInput arpInput = new ArpResponderInput.ArpReponderInputBuilder().setDpId(dpnId)
101                         .setInterfaceName(interfaceName).setSpa(subnetToDhcp.get().getPortFixedip())
102                         .setLportTag(interfaceDel.getIfIndex()).buildForRemoveFlow();
103                 elanService.removeArpResponderFlow(arpInput);
104             }
105         }
106         unInstallDhcpEntries(interfaceDel.getName(), dpnId, futures);
107         return futures;
108     }
109
110     private void unInstallDhcpEntries(String interfaceName, BigInteger dpId, List<ListenableFuture<Void>> futures) {
111         String vmMacAddress = getAndRemoveVmMacAddress(interfaceName);
112         WriteTransaction flowTx = dataBroker.newWriteOnlyTransaction();
113         dhcpManager.unInstallDhcpEntries(dpId, vmMacAddress, flowTx);
114         futures.add(flowTx.submit());
115     }
116
117     private String getAndRemoveVmMacAddress(String interfaceName) {
118         InstanceIdentifier<InterfaceNameMacAddress> instanceIdentifier =
119                 InstanceIdentifier.builder(InterfaceNameMacAddresses.class)
120                         .child(InterfaceNameMacAddress.class, new InterfaceNameMacAddressKey(interfaceName)).build();
121         Optional<InterfaceNameMacAddress> existingEntry =
122                 MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
123         if (existingEntry.isPresent()) {
124             String vmMacAddress = existingEntry.get().getMacAddress();
125             LOG.trace("Entry for interface found in InterfaceNameVmMacAddress map {}, {}", interfaceName, vmMacAddress);
126             MDSALDataStoreUtils.asyncRemove(dataBroker, LogicalDatastoreType.OPERATIONAL,
127                     instanceIdentifier, DEFAULT_CALLBACK);
128             return vmMacAddress;
129         }
130         LOG.trace("Entry for interface {} missing in InterfaceNameVmMacAddress map", interfaceName);
131         return null;
132     }
133 }