Merge "Fixed IBgpManager by moving it, as it was in clearly wrong directory"
[vpnservice.git] / neutronvpn / neutronvpn-impl / src / main / java / org / opendaylight / vpnservice / 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.vpnservice.neutronvpn;
9
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.CheckedFuture;
12 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
13 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
14 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
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.controller.md.sal.common.api.data.ReadFailedException;
18 import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
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.yangtools.concepts.ListenerRegistration;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31 import java.util.ArrayList;
32 import java.util.HashSet;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Set;
36
37
38 public class NeutronRouterChangeListener extends AbstractDataChangeListener<Router> implements AutoCloseable {
39     private static final Logger LOG = LoggerFactory.getLogger(NeutronRouterChangeListener.class);
40
41     private ListenerRegistration<DataChangeListener> listenerRegistration;
42     private final DataBroker broker;
43     private NeutronvpnManager nvpnManager;
44
45
46     public NeutronRouterChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr) {
47         super(Router.class);
48         broker = db;
49         nvpnManager = nVpnMgr;
50         registerListener(db);
51     }
52
53     @Override
54     public void close() throws Exception {
55         if (listenerRegistration != null) {
56             try {
57                 listenerRegistration.close();
58             } catch (final Exception e) {
59                 LOG.error("Error when cleaning up DataChangeListener.", e);
60             }
61             listenerRegistration = null;
62         }
63         LOG.info("N_Router listener Closed");
64     }
65
66
67     private void registerListener(final DataBroker db) {
68         try {
69             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
70                     InstanceIdentifier.create(Neutron.class).child(Routers.class).child(Router.class),
71                     NeutronRouterChangeListener.this, DataChangeScope.SUBTREE);
72         } catch (final Exception e) {
73             LOG.error("Neutron Manager Router DataChange listener registration fail!", e);
74             throw new IllegalStateException("Neutron Manager Router DataChange listener registration failed.", e);
75         }
76     }
77
78     private Set<Port> getInterfaces(final Uuid deviceId) {
79         final Set<Port> interfaces = new HashSet<>();
80         InstanceIdentifier<Ports> path = InstanceIdentifier.create(Neutron.class).child(Ports.class);
81
82         try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
83             final CheckedFuture<Optional<Ports>, ReadFailedException> future = tx.read(LogicalDatastoreType.CONFIGURATION, path);
84             Optional<Ports> optional = future.checkedGet();
85             if (optional.isPresent()) {
86                 for (final Port port : optional.get().getPort()) {
87                     if (port.getDeviceOwner().equals("network:router_interface") && port.getDeviceId().equals(deviceId.getValue())) {
88                         interfaces.add(port);
89                     }
90                 }
91             }
92         } catch (final ReadFailedException e) {
93             LOG.warn("Failed to read {}", path, e);
94         }
95
96         return interfaces;
97     }
98
99     @Override
100     protected void add(InstanceIdentifier<Router> identifier, Router input) {
101         if (LOG.isTraceEnabled()) {
102             LOG.trace("Adding Router : key: " + identifier + ", value=" + input);
103         }
104         // Create internal VPN
105         nvpnManager.createL3Vpn(input.getUuid(), null, null, null, null, null, input.getUuid(), null);
106     }
107
108     @Override
109     protected void remove(InstanceIdentifier<Router> identifier, Router input) {
110         if (LOG.isTraceEnabled()) {
111             LOG.trace("Removing router : key: " + identifier + ", value=" + input);
112         }
113         Uuid routerId = input.getUuid();
114         Set<Port> routerInterfaces = this.getInterfaces(input.getUuid());
115         List<Uuid> routerSubnetIds = new ArrayList<>();
116         if (!routerInterfaces.isEmpty()) {
117             Set<Uuid> uuids = new HashSet<>();
118             for (Port port : routerInterfaces) {
119                 for (FixedIps fixedIps : port.getFixedIps()) {
120                     uuids.add(fixedIps.getSubnetId());
121                 }
122             }
123             routerSubnetIds.addAll(uuids);
124         }
125         nvpnManager.handleNeutronRouterDeleted(routerId, routerSubnetIds);
126     }
127
128     @Override
129     protected void update(InstanceIdentifier<Router> identifier, Router original, Router update) {
130         if (LOG.isTraceEnabled()) {
131             LOG.trace("Updating Router : key: " + identifier + ", original value=" + original + ", update value=" +
132                     update);
133         }
134         Uuid routerId = update.getUuid();
135         Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId, true);
136         // internal vpn always present in case external vpn not found
137         if (vpnId == null) {
138             vpnId = routerId;
139         }
140         List<Routes> oldRoutes = (original.getRoutes() != null) ? original.getRoutes() : new ArrayList<Routes>();
141         List<Routes> newRoutes = (update.getRoutes() != null) ? update.getRoutes() : new ArrayList<Routes>();
142         if (!oldRoutes.equals(newRoutes)) {
143             Iterator<Routes> iterator = newRoutes.iterator();
144             while (iterator.hasNext()) {
145                 Routes route = iterator.next();
146                 if (oldRoutes.remove(route)) {
147                     iterator.remove();
148                 }
149             }
150             nvpnManager.addAdjacencyforExtraRoute(newRoutes, true, null);
151             if (!oldRoutes.isEmpty()) {
152                 nvpnManager.removeAdjacencyforExtraRoute(oldRoutes);
153             }
154         }
155     }
156 }