Switch to JDT annotations for Nullable and NonNull
[netvirt.git] / 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 static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
12
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.math.BigInteger;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.List;
18 import java.util.concurrent.Callable;
19 import java.util.concurrent.ExecutionException;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.genius.infra.Datastore;
23 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
24 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
25 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
26 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
27 import org.opendaylight.netvirt.dhcpservice.DhcpExternalTunnelManager;
28 import org.opendaylight.netvirt.dhcpservice.DhcpManager;
29 import org.opendaylight.netvirt.dhcpservice.DhcpServiceUtils;
30 import org.opendaylight.netvirt.elan.arp.responder.ArpResponderInput;
31 import org.opendaylight.netvirt.elanmanager.api.IElanService;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710.InterfaceNameMacAddresses;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddress;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddressKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710.subnet.dhcp.port.data.SubnetToDhcpPort;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 public class DhcpInterfaceRemoveJob implements Callable<List<ListenableFuture<Void>>> {
45
46     private static final Logger LOG = LoggerFactory.getLogger(DhcpInterfaceRemoveJob.class);
47
48     private final DhcpManager dhcpManager;
49     private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
50     private final DataBroker dataBroker;
51     private final ManagedNewTransactionRunner txRunner;
52     private final Interface interfaceDel;
53     private final BigInteger dpnId;
54     private final IInterfaceManager interfaceManager;
55     private final IElanService elanService;
56     private final Port port;
57
58     public DhcpInterfaceRemoveJob(DhcpManager dhcpManager, DhcpExternalTunnelManager dhcpExternalTunnelManager,
59                                   DataBroker dataBroker,
60                                   Interface interfaceDel, BigInteger dpnId, IInterfaceManager interfaceManager,
61                                   IElanService elanService, Port port) {
62         this.dhcpManager = dhcpManager;
63         this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
64         this.dataBroker = dataBroker;
65         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
66         this.interfaceDel = interfaceDel;
67         this.dpnId = dpnId;
68         this.interfaceManager = interfaceManager;
69         this.elanService = elanService;
70         this.port = port;
71     }
72
73     @Override
74     public List<ListenableFuture<Void>> call() throws ExecutionException, InterruptedException {
75         String interfaceName = interfaceDel.getName();
76         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
77                 interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName);
78         if (iface != null) {
79             IfTunnel tunnelInterface = iface.augmentation(IfTunnel.class);
80             if (tunnelInterface != null && !tunnelInterface.isInternal()) {
81                 IpAddress tunnelIp = tunnelInterface.getTunnelDestination();
82                 List<BigInteger> dpns = DhcpServiceUtils.getListOfDpns(dataBroker);
83                 if (dpns.contains(dpnId)) {
84                     return dhcpExternalTunnelManager.handleTunnelStateDown(tunnelIp, dpnId);
85                 }
86                 return Collections.emptyList();
87             }
88         }
89         List<ListenableFuture<Void>> futures = new ArrayList<>();
90         // Support for VM migration use cases.
91         futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
92             tx -> DhcpServiceUtils.unbindDhcpService(interfaceName, tx)));
93         java.util.Optional<String> subnetId = DhcpServiceUtils.getNeutronSubnetId(port);
94         if (subnetId.isPresent()) {
95             java.util.Optional<SubnetToDhcpPort> subnetToDhcp = DhcpServiceUtils.getSubnetDhcpPortData(dataBroker,
96                     subnetId.get());
97             if (subnetToDhcp.isPresent()) {
98                 LOG.trace("Removing ArpResponder flow for last interface {} on DPN {}", interfaceName, dpnId);
99                 ArpResponderInput arpInput = new ArpResponderInput.ArpReponderInputBuilder().setDpId(dpnId)
100                         .setInterfaceName(interfaceName).setSpa(subnetToDhcp.get().getPortFixedip())
101                         .setLportTag(interfaceDel.getIfIndex()).buildForRemoveFlow();
102                 elanService.removeArpResponderFlow(arpInput);
103             }
104         }
105         futures.addAll(unInstallDhcpEntries(interfaceDel.getName(), dpnId));
106         return futures;
107     }
108
109     private List<ListenableFuture<Void>> unInstallDhcpEntries(String interfaceName, BigInteger dpId)
110         throws ExecutionException, InterruptedException {
111         String vmMacAddress = txRunner.applyWithNewReadWriteTransactionAndSubmit(OPERATIONAL,
112             tx -> getAndRemoveVmMacAddress(tx, interfaceName)).get();
113         return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
114             tx -> dhcpManager.unInstallDhcpEntries(dpId, vmMacAddress, tx)));
115     }
116
117     @Nullable
118     private String getAndRemoveVmMacAddress(TypedReadWriteTransaction<Datastore.Operational> tx, String interfaceName)
119         throws ExecutionException, InterruptedException {
120         InstanceIdentifier<InterfaceNameMacAddress> instanceIdentifier =
121                 InstanceIdentifier.builder(InterfaceNameMacAddresses.class)
122                         .child(InterfaceNameMacAddress.class, new InterfaceNameMacAddressKey(interfaceName)).build();
123         return tx.read(instanceIdentifier).get().toJavaUtil().map(
124             interfaceNameMacAddress -> {
125                 String vmMacAddress = interfaceNameMacAddress.getMacAddress();
126                 LOG.trace("Entry for interface found in InterfaceNameVmMacAddress map {}, {}", interfaceName,
127                         vmMacAddress);
128                 tx.delete(instanceIdentifier);
129                 return vmMacAddress;
130             }).orElseGet(() -> {
131                 LOG.trace("Entry for interface {} missing in InterfaceNameVmMacAddress map", interfaceName);
132                 return null;
133             });
134     }
135 }