NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / dhcpservice / impl / src / main / java / org / opendaylight / netvirt / dhcpservice / jobs / DhcpInterfaceAddJob.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.util.ArrayList;
15 import java.util.Collections;
16 import java.util.List;
17 import java.util.concurrent.Callable;
18 import java.util.concurrent.ExecutionException;
19 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
20 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
21 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
22 import org.opendaylight.genius.mdsalutil.NwConstants;
23 import org.opendaylight.mdsal.binding.api.DataBroker;
24 import org.opendaylight.netvirt.dhcpservice.DhcpExternalTunnelManager;
25 import org.opendaylight.netvirt.dhcpservice.DhcpManager;
26 import org.opendaylight.netvirt.dhcpservice.DhcpServiceUtils;
27 import org.opendaylight.netvirt.dhcpservice.api.DhcpMConstants;
28 import org.opendaylight.netvirt.elan.arp.responder.ArpResponderInput.ArpReponderInputBuilder;
29 import org.opendaylight.netvirt.elan.arp.responder.ArpResponderUtil;
30 import org.opendaylight.netvirt.elanmanager.api.IElanService;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
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.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710.subnet.dhcp.port.data.SubnetToDhcpPort;
38 import org.opendaylight.yangtools.yang.common.Uint64;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 public class DhcpInterfaceAddJob implements Callable<List<? extends ListenableFuture<?>>> {
43
44     private static final Logger LOG = LoggerFactory.getLogger(DhcpInterfaceAddJob.class);
45
46     private final DhcpManager dhcpManager;
47     private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
48     private final DataBroker dataBroker;
49     private final ManagedNewTransactionRunner txRunner;
50     private final Interface interfaceAdd;
51     private final Uint64 dpnId;
52     private final IInterfaceManager interfaceManager;
53     private final IElanService elanService;
54     private final ItmRpcService itmRpcService;
55
56     public DhcpInterfaceAddJob(DhcpManager dhcpManager, DhcpExternalTunnelManager dhcpExternalTunnelManager,
57                                DataBroker dataBroker, Interface interfaceAdd, Uint64 dpnId,
58                                IInterfaceManager interfaceManager, IElanService elanService,
59                                ItmRpcService itmRpcService) {
60         this.dhcpManager = dhcpManager;
61         this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
62         this.dataBroker = dataBroker;
63         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
64         this.interfaceAdd = interfaceAdd;
65         this.dpnId = dpnId;
66         this.interfaceManager = interfaceManager;
67         this.elanService = elanService;
68         this.itmRpcService = itmRpcService;
69     }
70
71     @Override
72     public List<ListenableFuture<Void>> call() throws ExecutionException, InterruptedException {
73         String interfaceName = interfaceAdd.getName();
74         LOG.trace("Received add DCN for interface {}, dpid {}", interfaceName, dpnId);
75         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
76                 interfaceManager.getInterfaceInfoFromConfigDataStore(interfaceName);
77         if (iface != null) {
78             IfTunnel tunnelInterface = iface.augmentation(IfTunnel.class);
79             if (tunnelInterface != null && !tunnelInterface.isInternal()) {
80                 IpAddress tunnelIp = tunnelInterface.getTunnelDestination();
81                 List<Uint64> dpns = DhcpServiceUtils.getListOfDpns(dataBroker);
82                 if (dpns.contains(dpnId)) {
83                     return dhcpExternalTunnelManager.handleTunnelStateUp(tunnelIp, dpnId);
84                 }
85                 return Collections.emptyList();
86             }
87         }
88         if (!dpnId.equals(DhcpMConstants.INVALID_DPID)) {
89             Port port = dhcpManager.getNeutronPort(interfaceName);
90             Subnet subnet = dhcpManager.getNeutronSubnet(port);
91             if (null == subnet || !subnet.isEnableDhcp()) {
92                 LOG.debug("DHCP is not enabled for port {}", port.getName());
93                 return Collections.emptyList();
94             }
95             List<ListenableFuture<Void>> futures = new ArrayList<>();
96             // Support for VM migration use cases.
97             futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
98                 tx -> DhcpServiceUtils.bindDhcpService(interfaceName, NwConstants.DHCP_TABLE, tx)));
99             LOG.info("DhcpInterfaceEventListener add isEnableDhcp:{}", subnet.isEnableDhcp());
100             futures.addAll(installDhcpEntries(interfaceAdd.getName(), dpnId));
101             LOG.trace("Checking ElanDpnInterface {} for dpn {} ", interfaceName, dpnId);
102             String subnetId = subnet.getUuid().getValue();
103             java.util.Optional<SubnetToDhcpPort> subnetToDhcp = DhcpServiceUtils
104                     .getSubnetDhcpPortData(dataBroker, subnetId);
105             if (!subnetToDhcp.isPresent()) {
106                 return Collections.emptyList();
107             }
108             LOG.trace("Installing the Arp responder for interface {} with DHCP MAC {} & IP {}.", interfaceName,
109                     subnetToDhcp.get().getPortMacaddress(), subnetToDhcp.get().getPortFixedip());
110             ArpReponderInputBuilder builder = new ArpReponderInputBuilder();
111             builder.setDpId(dpnId.toJava()).setInterfaceName(interfaceName).setSpa(subnetToDhcp.get().getPortFixedip())
112                     .setSha(subnetToDhcp.get().getPortMacaddress()).setLportTag(interfaceAdd.getIfIndex());
113             builder.setInstructions(ArpResponderUtil.getInterfaceInstructions(interfaceManager, interfaceName,
114                     subnetToDhcp.get().getPortFixedip(), subnetToDhcp.get().getPortMacaddress(), itmRpcService));
115             elanService.addArpResponderFlow(builder.buildForInstallFlow());
116             return futures;
117         }
118         return Collections.emptyList();
119     }
120
121     private List<ListenableFuture<Void>> installDhcpEntries(String interfaceName, Uint64 dpId)
122         throws ExecutionException, InterruptedException {
123         String vmMacAddress = txRunner.applyWithNewReadWriteTransactionAndSubmit(OPERATIONAL,
124             tx -> DhcpServiceUtils.getAndUpdateVmMacAddress(tx, interfaceName, dhcpManager)).get();
125         return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
126             tx -> dhcpManager.installDhcpEntries(dpId, vmMacAddress, tx)));
127     }
128 }