2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.vpnservice.neutronvpn;
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;
38 public class NeutronRouterChangeListener extends AbstractDataChangeListener<Router> implements AutoCloseable {
39 private static final Logger LOG = LoggerFactory.getLogger(NeutronRouterChangeListener.class);
41 private ListenerRegistration<DataChangeListener> listenerRegistration;
42 private final DataBroker broker;
43 private NeutronvpnManager nvpnManager;
46 public NeutronRouterChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr) {
49 nvpnManager = nVpnMgr;
54 public void close() throws Exception {
55 if (listenerRegistration != null) {
57 listenerRegistration.close();
58 } catch (final Exception e) {
59 LOG.error("Error when cleaning up DataChangeListener.", e);
61 listenerRegistration = null;
63 LOG.info("N_Router listener Closed");
67 private void registerListener(final DataBroker db) {
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);
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);
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())) {
92 } catch (final ReadFailedException e) {
93 LOG.warn("Failed to read {}", path, e);
100 protected void add(InstanceIdentifier<Router> identifier, Router input) {
101 if (LOG.isTraceEnabled()) {
102 LOG.trace("Adding Router : key: " + identifier + ", value=" + input);
104 // Create internal VPN
105 nvpnManager.createL3Vpn(input.getUuid(), null, null, null, null, null, input.getUuid(), null);
109 protected void remove(InstanceIdentifier<Router> identifier, Router input) {
110 if (LOG.isTraceEnabled()) {
111 LOG.trace("Removing router : key: " + identifier + ", value=" + input);
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());
123 routerSubnetIds.addAll(uuids);
125 nvpnManager.handleNeutronRouterDeleted(routerId, routerSubnetIds);
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=" +
134 Uuid routerId = update.getUuid();
135 Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId, true);
136 // internal vpn always present in case external vpn not found
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)) {
150 nvpnManager.addAdjacencyforExtraRoute(newRoutes, true, null);
151 if (!oldRoutes.isEmpty()) {
152 nvpnManager.removeAdjacencyforExtraRoute(oldRoutes);