DHCP Handling for TOR VM
[vpnservice.git] / dhcpservice / dhcpservice-impl / src / main / java / org / opendaylight / vpnservice / dhcpservice / DhcpLogicalSwitchListener.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.vpnservice.dhcpservice;
9
10 import java.math.BigInteger;
11 import java.util.List;
12 import java.util.concurrent.ConcurrentMap;
13
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
16 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
19 import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
20 import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
21 import org.opendaylight.vpnservice.neutronvpn.api.l2gw.utils.L2GatewayCacheUtils;
22 import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundConstants;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
26 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
27 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
28 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
30 import org.opendaylight.yangtools.concepts.ListenerRegistration;
31 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 public class DhcpLogicalSwitchListener extends AbstractDataChangeListener<LogicalSwitches> implements AutoCloseable {
36
37     private static final Logger logger = LoggerFactory.getLogger(DhcpLogicalSwitchListener.class);
38     private DhcpExternalTunnelManager dhcpExternalTunnelManager;
39     private ListenerRegistration<DataChangeListener> listenerRegistration;
40     private DataBroker dataBroker;
41
42     public DhcpLogicalSwitchListener(DhcpExternalTunnelManager dhcpManager, DataBroker dataBroker) {
43         super(LogicalSwitches.class);
44         this.dhcpExternalTunnelManager = dhcpManager;
45         this.dataBroker = dataBroker;
46         registerListener();
47     }
48
49     private void registerListener() {
50         try {
51             listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
52                     getWildCardPath(), DhcpLogicalSwitchListener.this, DataChangeScope.SUBTREE);
53         } catch (final Exception e) {
54             logger.error("DhcpLogicalSwitchListener DataChange listener registration fail!", e);
55             throw new IllegalStateException("DhcpLogicalSwitchListener registration Listener failed.", e);
56         }
57     }
58
59     private InstanceIdentifier<LogicalSwitches> getWildCardPath() {
60         return InstanceIdentifier.create(NetworkTopology.class)
61                 .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID))
62                 .child(Node.class).augmentation(HwvtepGlobalAugmentation.class)
63                 .child(LogicalSwitches.class);
64     }
65
66     @Override
67     public void close() throws Exception {
68         if (listenerRegistration != null) {
69             try {
70                 listenerRegistration.close();
71             } catch (final Exception e) {
72                 logger.error("Error when cleaning up DataChangeListener.", e);
73             }
74             listenerRegistration = null;
75         }
76         logger.info("DhcpLogicalSwitchListener Closed");
77     }
78
79     @Override
80     protected void remove(InstanceIdentifier<LogicalSwitches> identifier,
81             LogicalSwitches del) {
82         logger.trace("Received LogicalSwitch remove DCN");
83         String elanInstanceName = del.getLogicalSwitchUuid().toString();
84         ConcurrentMap<String, L2GatewayDevice> devices  = L2GatewayCacheUtils.getCache();
85         String nodeId = identifier.firstKeyOf(Node.class).getNodeId().getValue();
86         L2GatewayDevice targetDevice = null;
87         for (L2GatewayDevice device : devices.values()) {
88             if (nodeId.equals(device.getHwvtepNodeId())) {
89                 targetDevice = device;
90                 break;
91             }
92         }
93         if (targetDevice == null) {
94             logger.error("Logical Switch Device with name {} is not present in L2GW cache", elanInstanceName);
95             return;
96         }
97         IpAddress tunnelIp = targetDevice.getTunnelIp();
98         handleLogicalSwitchRemove(elanInstanceName, tunnelIp);
99     }
100
101     @Override
102     protected void update(InstanceIdentifier<LogicalSwitches> identifier,
103             LogicalSwitches original, LogicalSwitches update) {
104         logger.trace("Received LogicalSwitch update DCN");
105
106     }
107
108     @Override
109     protected void add(InstanceIdentifier<LogicalSwitches> identifier,
110             LogicalSwitches add) {
111         logger.trace("Received LogicalSwitch add DCN");
112         String elanInstanceName = add.getHwvtepNodeName().getValue();
113         ConcurrentMap<String, L2GatewayDevice> devices  = L2GatewayCacheUtils.getCache();
114         String nodeId = identifier.firstKeyOf(Node.class).getNodeId().getValue();
115         L2GatewayDevice targetDevice = null;
116         for (L2GatewayDevice device : devices.values()) {
117             if (nodeId.equals(device.getHwvtepNodeId())) {
118                 targetDevice = device;
119                 break;
120             }
121         }
122         if (targetDevice == null) {
123             logger.error("Logical Switch Device with name {} is not present in L2GW cache", elanInstanceName);
124             return;
125         }
126         IpAddress tunnelIp = targetDevice.getTunnelIp();
127         handleLogicalSwitchAdd(elanInstanceName, tunnelIp);
128
129     }
130
131     private void handleLogicalSwitchRemove(String elanInstanceName, IpAddress tunnelIp) {
132         BigInteger designatedDpnId;
133         designatedDpnId = dhcpExternalTunnelManager.readDesignatedSwitchesForExternalTunnel(tunnelIp, elanInstanceName);
134         if (designatedDpnId == null || designatedDpnId.equals(DHCPMConstants.INVALID_DPID)) {
135             logger.error("Could not find designated DPN ID");
136             return;
137         }
138         dhcpExternalTunnelManager.removeDesignatedSwitchForExternalTunnel(designatedDpnId, tunnelIp, elanInstanceName);
139     }
140
141     private void handleLogicalSwitchAdd(String elanInstanceName, IpAddress tunnelIp) {
142         List<BigInteger> dpns = DhcpServiceUtils.getListOfDpns(dataBroker);
143         BigInteger designatedDpnId;
144         designatedDpnId = dhcpExternalTunnelManager.designateDpnId(tunnelIp, elanInstanceName, dpns);
145         if (designatedDpnId == null || designatedDpnId.equals(DHCPMConstants.INVALID_DPID)) {
146             logger.error("Unable to designate a DPN");
147             return;
148         }
149     }
150 }