Bug 8346 - Conflicting modification for vpnNextHops.
[netvirt.git] / vpnservice / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / netvirt / vpnmanager / VpnOpStatusListener.java
1 /*
2  * Copyright (c) 2015 - 2017 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.vpnmanager;
9
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import java.util.ArrayList;
13 import java.util.List;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
18 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
19 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
20 import org.opendaylight.genius.utils.SystemPropertyReader;
21 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
22 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
23 import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.Vpn;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 public class VpnOpStatusListener extends AsyncDataTreeChangeListenerBase<VpnInstanceOpDataEntry, VpnOpStatusListener>
33     implements AutoCloseable {
34     private static final Logger LOG = LoggerFactory.getLogger(VpnOpStatusListener.class);
35     private final DataBroker dataBroker;
36     private final IBgpManager bgpManager;
37     private final IdManagerService idManager;
38     private final IFibManager fibManager;
39     private final IMdsalApiManager mdsalManager;
40     private final VpnFootprintService vpnFootprintService;
41
42     public VpnOpStatusListener(final DataBroker dataBroker, final IBgpManager bgpManager,
43                                final IdManagerService idManager, final IFibManager fibManager,
44                                final IMdsalApiManager mdsalManager, final VpnFootprintService vpnFootprintService) {
45         super(VpnInstanceOpDataEntry.class, VpnOpStatusListener.class);
46         this.dataBroker = dataBroker;
47         this.bgpManager = bgpManager;
48         this.idManager = idManager;
49         this.fibManager = fibManager;
50         this.mdsalManager = mdsalManager;
51         this.vpnFootprintService = vpnFootprintService;
52     }
53
54     public void start() {
55         LOG.info("{} start", getClass().getSimpleName());
56         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
57     }
58
59     @Override
60     protected InstanceIdentifier<VpnInstanceOpDataEntry> getWildCardPath() {
61         return InstanceIdentifier.create(VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class);
62     }
63
64     @Override
65     protected VpnOpStatusListener getDataTreeChangeListener() {
66         return VpnOpStatusListener.this;
67     }
68
69     @Override
70     protected void remove(InstanceIdentifier<VpnInstanceOpDataEntry> identifier, VpnInstanceOpDataEntry value) {
71         LOG.info("remove: Ignoring vpn Op {} with rd {}", value.getVpnInstanceName(), value.getVrfId());
72     }
73
74     @Override
75     protected void update(InstanceIdentifier<VpnInstanceOpDataEntry> identifier,
76                           VpnInstanceOpDataEntry original, VpnInstanceOpDataEntry update) {
77         LOG.info("update: Processing update for vpn {} with rd {}", update.getVpnInstanceName(), update.getVrfId());
78         if (update.getVpnState() == VpnInstanceOpDataEntry.VpnState.PendingDelete
79                 && vpnFootprintService.isVpnFootPrintCleared(update)) {
80             //Cleanup VPN data
81             final String vpnName = update.getVpnInstanceName();
82             final List<String> rds = update.getRd();
83             String primaryRd = update.getVrfId();
84             final long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
85             DataStoreJobCoordinator djc = DataStoreJobCoordinator.getInstance();
86             djc.enqueueJob("VPN-" + update.getVpnInstanceName(), () -> {
87                 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
88
89                 // Clean up VpnInstanceToVpnId from Config DS
90                 VpnUtil.removeVpnIdToVpnInstance(dataBroker, vpnId, writeTxn);
91                 VpnUtil.removeVpnInstanceToVpnId(dataBroker, vpnName, writeTxn);
92                 LOG.trace("Removed vpnIdentifier for  rd{} vpnname {}", primaryRd, vpnName);
93                 // Clean up FIB Entries Config DS
94                 fibManager.removeVrfTable(dataBroker, primaryRd, null);
95                 if (VpnUtil.isBgpVpn(vpnName, primaryRd)) {
96                     rds.parallelStream().forEach(rd -> bgpManager.deleteVrf(rd, false));
97                 }
98                 // Clean up VPNExtraRoutes Operational DS
99                 InstanceIdentifier<Vpn> vpnToExtraroute = VpnExtraRouteHelper.getVpnToExtrarouteVpnIdentifier(vpnName);
100                 Optional<Vpn> optVpnToExtraroute = VpnUtil.read(dataBroker,
101                         LogicalDatastoreType.OPERATIONAL, vpnToExtraroute);
102                 if (optVpnToExtraroute.isPresent()) {
103                     VpnUtil.removeVpnExtraRouteForVpn(dataBroker, vpnName, writeTxn);
104                 }
105
106                 if (VpnUtil.isL3VpnOverVxLan(update.getL3vni())) {
107                     VpnUtil.removeExternalTunnelDemuxFlows(vpnName, dataBroker, mdsalManager);
108                 }
109
110                 // Clean up VPNInstanceOpDataEntry
111                 VpnUtil.removeVpnOpInstance(dataBroker, primaryRd, writeTxn);
112                 // Clean up PrefixToInterface Operational DS
113                 VpnUtil.removePrefixToInterfaceForVpnId(dataBroker, vpnId, writeTxn);
114
115                 // Clean up L3NextHop Operational DS
116                 VpnUtil.removeL3nexthopForVpnId(dataBroker, vpnId, writeTxn);
117
118                 // Release the ID used for this VPN back to IdManager
119                 VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnName);
120
121                 List<ListenableFuture<Void>> futures = new ArrayList<>();
122                 futures.add(writeTxn.submit());
123                 return futures;
124             }, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
125         }
126     }
127
128     @Override
129     protected void add(final InstanceIdentifier<VpnInstanceOpDataEntry> identifier,
130                        final VpnInstanceOpDataEntry value) {
131         LOG.debug("add: Ignoring vpn Op {} with rd {}", value.getVpnInstanceName(), value.getVrfId());
132     }
133 }