Fixes for floatingIP and cluster reboot issue for int/ext VPN
[netvirt.git] / vpnservice / neutronvpn / neutronvpn-impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronRouterChangeListener.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.neutronvpn;
9
10 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
11 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
12 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
13 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
14 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
15 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
20 import org.opendaylight.yangtools.concepts.ListenerRegistration;
21 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24 import java.util.ArrayList;
25 import java.util.Iterator;
26 import java.util.List;
27
28
29 public class NeutronRouterChangeListener extends AbstractDataChangeListener<Router> implements AutoCloseable {
30     private static final Logger LOG = LoggerFactory.getLogger(NeutronRouterChangeListener.class);
31
32     private ListenerRegistration<DataChangeListener> listenerRegistration;
33     private final DataBroker broker;
34     private NeutronvpnManager nvpnManager;
35     private NeutronvpnNatManager nvpnNatManager;
36
37
38     public NeutronRouterChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr, NeutronvpnNatManager
39             nVpnNatMgr) {
40         super(Router.class);
41         broker = db;
42         nvpnManager = nVpnMgr;
43         nvpnNatManager = nVpnNatMgr;
44         registerListener(db);
45     }
46
47     @Override
48     public void close() throws Exception {
49         if (listenerRegistration != null) {
50             try {
51                 listenerRegistration.close();
52             } catch (final Exception e) {
53                 LOG.error("Error when cleaning up DataChangeListener.", e);
54             }
55             listenerRegistration = null;
56         }
57         LOG.info("N_Router listener Closed");
58     }
59
60
61     private void registerListener(final DataBroker db) {
62         try {
63             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
64                     InstanceIdentifier.create(Neutron.class).child(Routers.class).child(Router.class),
65                     NeutronRouterChangeListener.this, DataChangeScope.SUBTREE);
66         } catch (final Exception e) {
67             LOG.error("Neutron Manager Router DataChange listener registration fail!", e);
68             throw new IllegalStateException("Neutron Manager Router DataChange listener registration failed.", e);
69         }
70     }
71
72     @Override
73     protected void add(InstanceIdentifier<Router> identifier, Router input) {
74         if (LOG.isTraceEnabled()) {
75             LOG.trace("Adding Router : key: " + identifier + ", value=" + input);
76         }
77         // Create internal VPN
78         nvpnManager.createL3InternalVpn(input.getUuid(), null, null, null, null, null, input.getUuid(), null);
79         NeutronvpnUtils.addToRouterCache(input);
80     }
81
82     @Override
83     protected void remove(InstanceIdentifier<Router> identifier, Router input) {
84         if (LOG.isTraceEnabled()) {
85             LOG.trace("Removing router : key: " + identifier + ", value=" + input);
86         }
87         Uuid routerId = input.getUuid();
88         //NOTE: Pass an empty routerSubnetIds list, as router interfaces
89         //will be removed from VPN by invocations from NeutronPortChangeListener
90         List<Uuid> routerSubnetIds = new ArrayList<>();
91         nvpnManager.handleNeutronRouterDeleted(routerId, routerSubnetIds);
92         NeutronvpnUtils.removeFromRouterCache(input);
93         // Handle router deletion for the NAT service
94         if (input.getExternalGatewayInfo() != null) {
95             Uuid extNetId = input.getExternalGatewayInfo().getExternalNetworkId();
96             nvpnNatManager.removeExternalNetworkFromRouter(extNetId, input);
97         }
98     }
99
100     @Override
101     protected void update(InstanceIdentifier<Router> identifier, Router original, Router update) {
102         if (LOG.isTraceEnabled()) {
103             LOG.trace("Updating Router : key: " + identifier + ", original value=" + original + ", update value=" +
104                     update);
105         }
106         Uuid routerId = update.getUuid();
107         Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId, true);
108         // internal vpn always present in case external vpn not found
109         if (vpnId == null) {
110             vpnId = routerId;
111         }
112         List<Routes> oldRoutes = (original.getRoutes() != null) ? original.getRoutes() : new ArrayList<>();
113         List<Routes> newRoutes = (update.getRoutes() != null) ? update.getRoutes() : new ArrayList<>();
114
115         if (!oldRoutes.equals(newRoutes)) {
116             Iterator<Routes> iterator = newRoutes.iterator();
117             while (iterator.hasNext()) {
118                 Routes route = iterator.next();
119                 if (oldRoutes.remove(route)) {
120                     iterator.remove();
121                 }
122             }
123             nvpnManager.addAdjacencyforExtraRoute(newRoutes, true, null);
124             if (!oldRoutes.isEmpty()) {
125                 nvpnManager.removeAdjacencyforExtraRoute(oldRoutes);
126             }
127         }
128         nvpnNatManager.handleExternalNetworkForRouter(original, update);
129     }
130 }