Merge "Updated BgpManager for Be"
[vpnservice.git] / neutronvpn / neutronvpn-impl / src / main / java / org / opendaylight / vpnservice / neutronvpn / NeutronPortChangeListener.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.neutronvpn;
9
10
11 import com.google.common.base.Optional;
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.MDSALUtil;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
28         .PortFixedipToPortNameBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
30         .PortNameToPortUuidBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.Subnetmap;
32 import org.opendaylight.yangtools.concepts.ListenerRegistration;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import java.util.ArrayList;
38 import java.util.Iterator;
39 import java.util.List;
40
41
42 public class NeutronPortChangeListener extends AbstractDataChangeListener<Port> implements AutoCloseable {
43     private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChangeListener.class);
44
45     private ListenerRegistration<DataChangeListener> listenerRegistration;
46     private final DataBroker broker;
47     private NeutronvpnManager nvpnManager;
48
49
50     public NeutronPortChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr) {
51         super(Port.class);
52         broker = db;
53         nvpnManager = nVpnMgr;
54         registerListener(db);
55     }
56
57     @Override
58     public void close() throws Exception {
59         if (listenerRegistration != null) {
60             try {
61                 listenerRegistration.close();
62             } catch (final Exception e) {
63                 LOG.error("Error when cleaning up DataChangeListener.", e);
64             }
65             listenerRegistration = null;
66         }
67         LOG.info("N_Port listener Closed");
68     }
69
70
71     private void registerListener(final DataBroker db) {
72         try {
73             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
74                     InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class),
75                     NeutronPortChangeListener.this, DataChangeScope.SUBTREE);
76         } catch (final Exception e) {
77             LOG.error("Neutron Manager Port DataChange listener registration fail!", e);
78             throw new IllegalStateException("Neutron Manager Port DataChange listener registration failed.", e);
79         }
80     }
81
82     @Override
83     protected void add(InstanceIdentifier<Port> identifier, Port input) {
84         if (LOG.isTraceEnabled()) {
85             LOG.trace("Adding Port : key: " + identifier + ", value=" + input);
86         }
87         handleNeutronPortCreated(input);
88
89     }
90
91     @Override
92     protected void remove(InstanceIdentifier<Port> identifier, Port input) {
93         if (LOG.isTraceEnabled()) {
94             LOG.trace("Removing Port : key: " + identifier + ", value=" + input);
95         }
96         handleNeutronPortDeleted(input);
97
98     }
99
100     @Override
101     protected void update(InstanceIdentifier<Port> identifier, Port original, Port update) {
102         if (LOG.isTraceEnabled()) {
103             LOG.trace("Updating Port : key: " + identifier + ", original value=" + original + ", update value=" +
104                     update);
105         }
106         List<FixedIps> oldIPs = (original.getFixedIps() != null) ? original.getFixedIps() : new ArrayList<FixedIps>();
107         List<FixedIps> newIPs = (update.getFixedIps() != null) ? update.getFixedIps() : new ArrayList<FixedIps>();
108
109         if (!oldIPs.equals(newIPs)) {
110             Iterator<FixedIps> iterator = newIPs.iterator();
111             while (iterator.hasNext()) {
112                 FixedIps ip = iterator.next();
113                 if (oldIPs.remove(ip)) {
114                     iterator.remove();
115                 }
116             }
117             handleNeutronPortUpdated(original, update);
118         }
119     }
120
121     private void handleNeutronPortCreated(Port port) {
122         LOG.info("Of-port-interface creation");
123         int portVlanId = NeutronvpnUtils.getVlanFromNeutronPort(port);
124         // Create of-port interface for this neutron port
125         createOfPortInterface(port, portVlanId);
126         LOG.debug("Add port to subnet");
127         // add port to local Subnets DS
128         Uuid vpnId = addPortToSubnets(port);
129
130         if (vpnId != null) {
131             // create vpn-interface on this neutron port
132             LOG.debug("Adding VPN Interface");
133             nvpnManager.createVpnInterface(vpnId, port);
134         }
135     }
136
137     private void handleNeutronPortDeleted(Port port) {
138         LOG.debug("Of-port-interface removal");
139         LOG.debug("Remove port from subnet");
140         // remove port from local Subnets DS
141         Uuid vpnId = removePortFromSubnets(port);
142
143         if (vpnId != null) {
144             // remove vpn-interface for this neutron port
145             LOG.debug("removing VPN Interface");
146             nvpnManager.deleteVpnInterface(port);
147         }
148         int portVlanId = NeutronvpnUtils.getVlanFromNeutronPort(port);
149         // Remove of-port interface for this neutron port
150         deleteOfPortInterface(port, portVlanId);
151
152     }
153
154     private void handleNeutronPortUpdated(Port portoriginal, Port portupdate) {
155         LOG.debug("Add port to subnet");
156         // add port FixedIPs to local Subnets DS
157         Uuid vpnIdup = addPortToSubnets(portupdate);
158
159         if (vpnIdup != null) {
160             nvpnManager.createVpnInterface(vpnIdup, portupdate);
161         }
162
163         // remove port FixedIPs from local Subnets DS
164         Uuid vpnIdor = removePortFromSubnets(portoriginal);
165
166         if (vpnIdor != null) {
167             nvpnManager.deleteVpnInterface(portoriginal);
168         }
169     }
170
171     private void createOfPortInterface(Port port, int portVlanId) {
172         String name = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
173         //String ifname = new StringBuilder(name).append(":").append(Integer.toString(portVlanId)).toString();
174         //Network network = NeutronvpnUtils.getNeutronNetwork(broker, port.getNetworkId());
175         //Boolean isVlanTransparent = network.isVlanTransparent();
176
177         LOG.debug("Creating OFPort Interface {}", name);
178         InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
179         try {
180             Optional<Interface> optionalInf = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
181                     interfaceIdentifier);
182             if (!optionalInf.isPresent()) {
183                 // handle these for trunkport extensions : portVlanId, isVlanTransparent
184                 Interface inf = new InterfaceBuilder().setEnabled(true).setName(name).setType(L2vlan.class).build();
185                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, inf);
186             } else {
187                 LOG.error("Interface {} is already present", name);
188             }
189         } catch (Exception e) {
190             LOG.error("failed to create interface {} due to the exception {} ", name, e.getMessage());
191         }
192
193         InstanceIdentifier portIdentifier = NeutronvpnUtils.buildPortNameToPortUuidIdentifier(name);
194         PortNameToPortUuidBuilder builder = new PortNameToPortUuidBuilder().setPortName(name).setPortId(port.getUuid());
195         MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, portIdentifier, builder.build());
196         LOG.debug("name-uuid map for port with name: {}, uuid: {} added to NeutronPortData DS", name, port.getUuid
197                 ());
198     }
199
200     private void deleteOfPortInterface(Port port, int portVlanId) {
201         String name = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
202         //String ifname = new StringBuilder(name).append(":").append(Integer.toString(portVlanId)).toString();
203         LOG.debug("Removing OFPort Interface {}", name);
204         InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
205         try {
206             Optional<Interface> optionalInf = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
207                     interfaceIdentifier);
208             if (optionalInf.isPresent()) {
209                 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, interfaceIdentifier);
210             } else {
211                 LOG.error("Interface {} is not present", name);
212             }
213         } catch (Exception e) {
214             LOG.error("Failed to delete interface {} due to the exception {}", name, e.getMessage());
215         }
216
217         InstanceIdentifier portIdentifier = NeutronvpnUtils.buildPortNameToPortUuidIdentifier(name);
218         MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, portIdentifier);
219         LOG.debug("name-uuid map for port with name: {}, uuid: {} deleted from NeutronPortData DS", name, port
220                 .getUuid());
221     }
222
223     // adds port to subnet list and creates vpnInterface
224     private Uuid addPortToSubnets(Port port) {
225         Uuid subnetId = null;
226         Uuid vpnId = null;
227         String name = NeutronvpnUtils.uuidToTapPortName(port.getUuid());
228
229         // find all subnets to which this port is associated
230         List<FixedIps> ips = port.getFixedIps();
231         for (FixedIps ip : ips) {
232             String ipValue = ip.getIpAddress().getIpv4Address().getValue();
233
234             InstanceIdentifier id = NeutronvpnUtils.buildFixedIpToPortNameIdentifier(ipValue);
235             PortFixedipToPortNameBuilder builder = new PortFixedipToPortNameBuilder().setPortFixedip(ipValue)
236                     .setPortName(name);
237             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, builder.build());
238             LOG.debug("fixedIp-name map for neutron port with fixedIp: {}, name: {} added to NeutronPortData DS",
239                     ipValue, name);
240
241             subnetId = ip.getSubnetId();
242             Subnetmap subnetmap = nvpnManager.updateSubnetNode(subnetId, null, null, null, null, port.getUuid());
243             if (vpnId == null && subnetmap != null) {
244                 vpnId = subnetmap.getVpnId();
245             }
246         }
247         return vpnId;
248     }
249
250     private Uuid removePortFromSubnets(Port port) {
251         Uuid subnetId = null;
252         Uuid vpnId = null;
253
254         // find all Subnets to which this port is associated
255         List<FixedIps> ips = port.getFixedIps();
256         for (FixedIps ip : ips) {
257             String ipValue = ip.getIpAddress().getIpv4Address().getValue();
258
259             InstanceIdentifier id = NeutronvpnUtils.buildFixedIpToPortNameIdentifier(ipValue);
260             MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
261             LOG.debug("fixedIp-name map for neutron port with fixedIp: {} deleted from NeutronPortData DS", ipValue);
262
263             subnetId = ip.getSubnetId();
264             Subnetmap subnetmap = nvpnManager.removeFromSubnetNode(subnetId, null, null, null, port.getUuid());
265             if (vpnId == null && subnetmap != null) {
266                 vpnId = subnetmap.getVpnId();
267             }
268         }
269         return vpnId;
270     }
271 }