1e4396bb950f43b42071f08ede3adeec0d3800a3
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / TunnelEndPointChangeListener.java
1 /*
2  * Copyright (c) 2016 Hewlett Packard Enterprise, Co. 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
9 package org.opendaylight.netvirt.vpnmanager;
10
11 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
13
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.ListenableFuture;
17 import com.google.common.util.concurrent.MoreExecutors;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Set;
23 import javax.annotation.PostConstruct;
24 import javax.inject.Inject;
25 import javax.inject.Singleton;
26 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
29 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
30 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
31 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
32 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
33 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
34 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
35 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import org.opendaylight.yangtools.yang.common.Uint32;
42 import org.opendaylight.yangtools.yang.common.Uint64;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 @Singleton
47 public class TunnelEndPointChangeListener
48     extends AsyncDataTreeChangeListenerBase<TunnelEndPoints, TunnelEndPointChangeListener> {
49     private static final Logger LOG = LoggerFactory.getLogger(TunnelEndPointChangeListener.class);
50
51     private final DataBroker broker;
52     private final ManagedNewTransactionRunner txRunner;
53     private final VpnInterfaceManager vpnInterfaceManager;
54     private final JobCoordinator jobCoordinator;
55     private final VpnUtil vpnUtil;
56     private final IFibManager fibManager;
57
58     @Inject
59     public TunnelEndPointChangeListener(final DataBroker broker, final VpnInterfaceManager vpnInterfaceManager,
60             final JobCoordinator jobCoordinator, VpnUtil vpnUtil, final IFibManager fibManager) {
61         super(TunnelEndPoints.class, TunnelEndPointChangeListener.class);
62         this.broker = broker;
63         this.txRunner = new ManagedNewTransactionRunnerImpl(broker);
64         this.vpnInterfaceManager = vpnInterfaceManager;
65         this.jobCoordinator = jobCoordinator;
66         this.vpnUtil = vpnUtil;
67         this.fibManager = fibManager;
68     }
69
70     @PostConstruct
71     public void start() {
72         LOG.info("{} start", getClass().getSimpleName());
73         registerListener(LogicalDatastoreType.CONFIGURATION, broker);
74     }
75
76     @Override
77     protected InstanceIdentifier<TunnelEndPoints> getWildCardPath() {
78         return InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class).child(TunnelEndPoints.class)
79             .build();
80     }
81
82     @Override
83     protected void remove(InstanceIdentifier<TunnelEndPoints> key, TunnelEndPoints tep) {
84     }
85
86     @Override
87     protected void update(InstanceIdentifier<TunnelEndPoints> key, TunnelEndPoints origTep,
88         TunnelEndPoints updatedTep) {
89     }
90
91     @Override
92     protected void add(InstanceIdentifier<TunnelEndPoints> key, TunnelEndPoints tep) {
93         Uint64 dpnId = key.firstIdentifierOf(DPNTEPsInfo.class).firstKeyOf(DPNTEPsInfo.class).getDPNID();
94         if (Uint64.ZERO.equals(dpnId)) {
95             LOG.warn("add: Invalid DPN id for TEP {}", tep.getInterfaceName());
96             return;
97         }
98
99         List<VpnInstance> vpnInstances = VpnHelper.getAllVpnInstances(broker);
100         if (vpnInstances == null || vpnInstances.isEmpty()) {
101             LOG.warn("add: dpnId: {}: tep: {}: No VPN instances defined", dpnId, tep.getInterfaceName());
102             return;
103         }
104
105         for (VpnInstance vpnInstance : vpnInstances) {
106             final String vpnName = vpnInstance.getVpnInstanceName();
107             final Uint32 vpnId = vpnUtil.getVpnId(vpnName);
108             LOG.info("add: Handling TEP {} add for VPN instance {}", tep.getInterfaceName(), vpnName);
109             final String primaryRd = vpnUtil.getPrimaryRd(vpnName);
110             if (!vpnUtil.isVpnPendingDelete(primaryRd)) {
111                 List<VpnInterfaces> vpnInterfaces = vpnUtil.getDpnVpnInterfaces(vpnInstance, dpnId);
112                 if (vpnInterfaces != null) {
113                     for (VpnInterfaces vpnInterface : vpnInterfaces) {
114                         String vpnInterfaceName = vpnInterface.getInterfaceName();
115                         jobCoordinator.enqueueJob("VPNINTERFACE-" + vpnInterfaceName,
116                             () -> {
117                                 final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
118                                         .rev140508.interfaces.state.Interface
119                                         interfaceState =
120                                         InterfaceUtils.getInterfaceStateFromOperDS(broker, vpnInterfaceName);
121                                 if (interfaceState == null) {
122                                     LOG.debug("add: Cannot retrieve interfaceState for vpnInterfaceName {}, "
123                                             + "cannot generate lPortTag and process adjacencies", vpnInterfaceName);
124                                     return Collections.emptyList();
125                                 }
126                                 final int lPortTag = interfaceState.getIfIndex();
127                                 List<ListenableFuture<Void>> futures = new ArrayList<>();
128                                 Set<String> prefixesForRefreshFib = new HashSet<>();
129                                 ListenableFuture<Void> writeConfigFuture =
130                                     txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
131                                         writeConfigTxn -> futures.add(
132                                             txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL,
133                                                 writeOperTxn -> futures.add(
134                                                     txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
135                                                         writeInvTxn ->
136                                                             vpnInterfaceManager.processVpnInterfaceAdjacencies(dpnId,
137                                                                 lPortTag, vpnName, primaryRd, vpnInterfaceName, vpnId,
138                                                                 writeConfigTxn, writeOperTxn, writeInvTxn,
139                                                                 interfaceState, prefixesForRefreshFib)
140                                                     )))));
141                                 Futures.addCallback(writeConfigFuture, new FutureCallback<Void>() {
142                                     @Override
143                                     public void onSuccess(Void voidObj) {
144                                         prefixesForRefreshFib.forEach(prefix -> {
145                                             fibManager.refreshVrfEntry(primaryRd, prefix);
146                                         });
147                                     }
148
149                                     @Override
150                                     public void onFailure(Throwable throwable) {
151                                         LOG.debug("addVpnInterface: write Tx config execution failed", throwable);
152                                     }
153                                 }, MoreExecutors.directExecutor());
154                                 futures.add(writeConfigFuture);
155                                 LOG.trace("add: Handled TEP {} add for VPN instance {} VPN interface {}",
156                                         tep.getInterfaceName(), vpnName, vpnInterfaceName);
157                                 return futures;
158                             });
159                     }
160                 }
161             } else {
162                 LOG.error("add: Ignoring addition of tunnel interface {} dpn {} for vpnInstance {} with primaryRd {},"
163                         + " as the VPN is already marked for deletion", tep.getInterfaceName(), dpnId,
164                         vpnName, primaryRd);
165             }
166         }
167     }
168
169     @Override
170     protected TunnelEndPointChangeListener getDataTreeChangeListener() {
171         return this;
172     }
173 }