5cc245653a097bdf6d4f4ac3b5f59344a06fd34c
[vpnservice.git] / dhcpservice / dhcpservice-impl / src / main / java / org / opendaylight / vpnservice / dhcpservice / DhcpInterfaceEventListener.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
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
15 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
18 import org.opendaylight.vpnservice.mdsalutil.MDSALDataStoreUtils;
19 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710.InterfaceNameMacAddresses;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddress;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddressBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddressKey;
28 import org.opendaylight.yangtools.concepts.ListenerRegistration;
29 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 import com.google.common.base.Optional;
34 import com.google.common.util.concurrent.FutureCallback;
35
36 public class DhcpInterfaceEventListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
37
38     private static final Logger logger = LoggerFactory.getLogger(DhcpInterfaceEventListener.class);
39     private DhcpManager dhcpManager;
40     private ListenerRegistration<DataChangeListener> listenerRegistration;
41     private DataBroker dataBroker;
42     private static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
43         public void onSuccess(Void result) {
44             logger.debug("Success in Datastore write operation");
45         }
46
47         public void onFailure(Throwable error) {
48             logger.error("Error in Datastore write operation", error);
49         }
50     };
51
52     public DhcpInterfaceEventListener(DhcpManager dhcpManager, DataBroker dataBroker) {
53         super(Interface.class);
54         this.dhcpManager = dhcpManager;
55         this.dataBroker = dataBroker;
56         registerListener();
57     }
58
59     private void registerListener() {
60         try {
61             listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
62                     getWildCardPath(), DhcpInterfaceEventListener.this, DataChangeScope.SUBTREE);
63         } catch (final Exception e) {
64             logger.error("DhcpInterfaceEventListener DataChange listener registration fail!", e);
65             throw new IllegalStateException("DhcpInterfaceEventListener registration Listener failed.", e);
66         }
67     }
68
69     private InstanceIdentifier<Interface> getWildCardPath() {
70         return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
71     }
72
73     @Override
74     public void close() throws Exception {
75         if (listenerRegistration != null) {
76             try {
77                 listenerRegistration.close();
78             } catch (final Exception e) {
79                 logger.error("Error when cleaning up DataChangeListener.", e);
80             }
81             listenerRegistration = null;
82         }
83         logger.info("Interface Manager Closed");
84     }
85
86
87     @Override
88     protected void remove(InstanceIdentifier<Interface> identifier,
89             Interface del) {
90         String interfaceName = del.getName();
91         List<String> ofportIds = del.getLowerLayerIf();
92         NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
93         BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
94         logger.trace("Received remove DCN for interface {} dpId {}", interfaceName, dpId);
95         unInstallDhcpEntries(interfaceName, dpId);
96     }
97
98     @Override
99     protected void update(InstanceIdentifier<Interface> identifier,
100             Interface original, Interface update) {
101     }
102
103     @Override
104     protected void add(InstanceIdentifier<Interface> identifier, Interface add) {
105         String interfaceName = add.getName();
106         List<String> ofportIds = add.getLowerLayerIf();
107         NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
108         BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
109         logger.trace("Received add DCN for interface {}, dpid {}", interfaceName, dpId);
110         installDhcpEntries(interfaceName, dpId);
111     }
112
113     private String getNeutronMacAddress(String interfaceName) {
114         Port port = dhcpManager.getNeutronPort(interfaceName);
115         if (port!=null) {
116             logger.trace("Port found in neutron. Interface Name {}, port {}", interfaceName, port);
117             return port.getMacAddress();
118         }
119         logger.trace("Port not found in neutron. Interface Name {}", interfaceName);
120         return null;
121     }
122
123     private void unInstallDhcpEntries(String interfaceName, BigInteger dpId) {
124         String vmMacAddress = getAndRemoveVmMacAddress(interfaceName);
125         dhcpManager.unInstallDhcpEntries(dpId, vmMacAddress);
126     }
127
128     private void installDhcpEntries(String interfaceName, BigInteger dpId) {
129         String vmMacAddress = getAndUpdateVmMacAddress(interfaceName);
130         dhcpManager.installDhcpEntries(dpId, vmMacAddress);
131     }
132
133     private String getAndUpdateVmMacAddress(String interfaceName) {
134         InstanceIdentifier<InterfaceNameMacAddress> instanceIdentifier = InstanceIdentifier.builder(InterfaceNameMacAddresses.class).child(InterfaceNameMacAddress.class, new InterfaceNameMacAddressKey(interfaceName)).build();
135         Optional<InterfaceNameMacAddress> existingEntry = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
136         if (!existingEntry.isPresent()) {
137             logger.trace("Entry for interface {} missing in InterfaceNameVmMacAddress map", interfaceName);
138             String vmMacAddress = getNeutronMacAddress(interfaceName);
139             if (vmMacAddress==null || vmMacAddress.isEmpty()) {
140                 return null;
141             }
142             logger.trace("Updating InterfaceNameVmMacAddress map with {}, {}", interfaceName,vmMacAddress);
143             InterfaceNameMacAddress interfaceNameMacAddress = new InterfaceNameMacAddressBuilder().setKey(new InterfaceNameMacAddressKey(interfaceName)).setInterfaceName(interfaceName).setMacAddress(vmMacAddress).build();
144             MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier, interfaceNameMacAddress);
145             return vmMacAddress;
146         }
147         return existingEntry.get().getMacAddress();
148     }
149
150     private String getAndRemoveVmMacAddress(String interfaceName) {
151         InstanceIdentifier<InterfaceNameMacAddress> instanceIdentifier = InstanceIdentifier.builder(InterfaceNameMacAddresses.class).child(InterfaceNameMacAddress.class, new InterfaceNameMacAddressKey(interfaceName)).build();
152         Optional<InterfaceNameMacAddress> existingEntry = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
153         if (existingEntry.isPresent()) {
154             String vmMacAddress = existingEntry.get().getMacAddress();
155             logger.trace("Entry for interface found in InterfaceNameVmMacAddress map {}, {}", interfaceName, vmMacAddress);
156             MDSALDataStoreUtils.asyncRemove(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier, DEFAULT_CALLBACK);
157             return vmMacAddress;
158         }
159         logger.trace("Entry for interface {} missing in InterfaceNameVmMacAddress map", interfaceName);
160         return null;
161     }
162 }