Clean up lambdas and streams
[netvirt.git] / vpnservice / bgpmanager / bgpmanager-impl / src / main / java / org / opendaylight / netvirt / bgpmanager / FibDSWriter.java
1 /*
2  * Copyright (c) 2015 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.bgpmanager;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.stream.Collectors;
16 import org.apache.commons.lang3.StringUtils;
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
20 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
21 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
22 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntry;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntryBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntryKey;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 public class FibDSWriter {
39     private static final Logger LOG = LoggerFactory.getLogger(FibDSWriter.class);
40     private final DataBroker dataBroker;
41     private final SingleTransactionDataBroker singleTxDB;
42
43     public FibDSWriter(final DataBroker dataBroker) {
44         this.dataBroker = dataBroker;
45         this.singleTxDB = new SingleTransactionDataBroker(dataBroker);
46     }
47
48     public synchronized void addFibEntryToDS(String rd, String macAddress, String prefix, List<String> nextHopList,
49                                              VrfEntry.EncapType encapType, int label, long l3vni,
50                                              String gatewayMacAddress, RouteOrigin origin) {
51         if (rd == null || rd.isEmpty()) {
52             LOG.error("Prefix {} not associated with vpn", prefix);
53             return;
54         }
55
56         Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
57         for (String nextHop : nextHopList) {
58             if (nextHop == null || nextHop.isEmpty()) {
59                 LOG.error("nextHop list contains null element");
60                 return;
61             }
62             LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nextHop, label);
63         }
64
65         // Looking for existing prefix in MDSAL database
66         InstanceIdentifier<VrfEntry> vrfEntryId =
67                 InstanceIdentifier.builder(FibEntries.class)
68                         .child(VrfTables.class, new VrfTablesKey(rd))
69                         .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
70
71         VrfEntryBuilder vrfEntryBuilder = new VrfEntryBuilder().setDestPrefix(prefix).setOrigin(origin.getValue());
72         buildVpnEncapSpecificInfo(vrfEntryBuilder, encapType, (long)label, l3vni, macAddress,
73                 gatewayMacAddress, nextHopList);
74         BgpUtil.update(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntryBuilder.build());
75     }
76
77     public void addMacEntryToDS(String rd, String macAddress, String prefix,
78                                 List<String> nextHopList, VrfEntry.EncapType encapType,
79                                 long l2vni, String gatewayMacAddress, RouteOrigin origin) {
80         if (StringUtils.isEmpty(rd)) {
81             LOG.error("Mac {} not associated with vpn", macAddress);
82             return;
83         }
84
85         Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
86         for (String nextHop : nextHopList) {
87             if (StringUtils.isEmpty(nextHop)) {
88                 LOG.error("nextHop list contains null element for macVrf");
89                 return;
90             }
91         }
92
93         MacVrfEntryBuilder macEntryBuilder = new MacVrfEntryBuilder().setOrigin(origin.getValue());
94         buildVpnEncapSpecificInfo(macEntryBuilder, encapType, l2vni, macAddress,
95                 gatewayMacAddress, nextHopList);
96         macEntryBuilder.setMac(macAddress);
97         macEntryBuilder.setDestPrefix(prefix);
98         InstanceIdentifier<MacVrfEntry> macEntryId =
99                 InstanceIdentifier.builder(FibEntries.class)
100                         .child(VrfTables.class, new VrfTablesKey(rd))
101                         .child(MacVrfEntry.class, new MacVrfEntryKey(macAddress)).build();
102         BgpUtil.update(dataBroker, LogicalDatastoreType.CONFIGURATION, macEntryId, macEntryBuilder.build());
103     }
104
105     private static void buildVpnEncapSpecificInfo(VrfEntryBuilder builder,
106             VrfEntry.EncapType encapType, long label, long l3vni, String macAddress,
107             String gatewayMac, List<String> nextHopList) {
108         if (!encapType.equals(VrfEntry.EncapType.Mplsgre)) {
109             builder.setL3vni(l3vni);
110         }
111         builder.setEncapType(encapType);
112         builder.setGatewayMacAddress(gatewayMac);
113         Long lbl = encapType.equals(VrfEntry.EncapType.Mplsgre) ? label : null;
114         List<RoutePaths> routePaths = nextHopList.stream()
115                         .filter(StringUtils::isNotEmpty)
116                         .map(nextHop -> FibHelper.buildRoutePath(nextHop, lbl)).collect(Collectors.toList());
117         builder.setRoutePaths(routePaths);
118     }
119
120     private static void buildVpnEncapSpecificInfo(MacVrfEntryBuilder builder,
121                                                   VrfEntry.EncapType encapType, long l2vni, String macAddress,
122                                                   String gatewayMac, List<String> nextHopList) {
123         builder.setEncapType(encapType);
124         builder.setGatewayMacAddress(gatewayMac);
125         builder.setL2vni(l2vni);
126         List<RoutePaths> routePaths = nextHopList.stream()
127                 .filter(StringUtils::isNotEmpty)
128                 .map(nextHop -> FibHelper.buildRoutePath(nextHop, null)).collect(Collectors.toList());
129         builder.setRoutePaths(routePaths);
130     }
131
132     public synchronized void removeFibEntryFromDS(String rd, String prefix) {
133
134         if (rd == null || rd.isEmpty()) {
135             LOG.error("Prefix {} not associated with vpn", prefix);
136             return;
137         }
138         LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
139
140         InstanceIdentifierBuilder<VrfEntry> idBuilder =
141                 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(
142                         VrfEntry.class, new VrfEntryKey(prefix));
143         InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
144         BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
145
146     }
147
148     public void removeMacEntryFromDS(String rd, String macAddress) {
149
150         if (StringUtils.isEmpty(rd)) {
151             LOG.error("Mac {} not associated with vpn", macAddress);
152             return;
153         }
154         LOG.debug("Removing Mac fib entry with Mac {} from vrf table for rd {}", macAddress, rd);
155
156         InstanceIdentifierBuilder<MacVrfEntry> idBuilder =
157                 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(
158                         MacVrfEntry.class, new MacVrfEntryKey(macAddress));
159         InstanceIdentifier<MacVrfEntry> macEntryId = idBuilder.build();
160         BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, macEntryId);
161
162     }
163
164     public synchronized void removeOrUpdateFibEntryFromDS(String rd, String prefix, String nextHop) {
165
166         if (rd == null || rd.isEmpty()) {
167             LOG.error("Prefix {} not associated with vpn", prefix);
168             return;
169         }
170         LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {} and nextHop {}",
171                 prefix, rd, nextHop);
172         try {
173             InstanceIdentifier<VrfEntry> vrfEntryId =
174                     InstanceIdentifier.builder(FibEntries.class)
175                     .child(VrfTables.class, new VrfTablesKey(rd))
176                     .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
177             Optional<VrfEntry> existingVrfEntry =
178                     singleTxDB.syncReadOptional(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
179             List<RoutePaths> routePaths =
180                     existingVrfEntry.transform(VrfEntry::getRoutePaths).or(Collections.EMPTY_LIST);
181             if (routePaths.size() == 1) {
182                 if (routePaths.get(0).getNexthopAddress().equals(nextHop)) {
183                     BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
184                 }
185             } else {
186                 routePaths.stream()
187                     .map(RoutePaths::getNexthopAddress)
188                     .filter(nextHopAddress -> nextHopAddress.equals(nextHop))
189                     .findFirst()
190                     .ifPresent(nh -> {
191                         InstanceIdentifier<RoutePaths> routePathId =
192                                 FibHelper.buildRoutePathId(rd, prefix, nextHop);
193                         BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION,
194                                 routePathId);
195                     });
196             }
197         } catch (ReadFailedException e) {
198             LOG.error("Error while reading vrfEntry for rd {}, prefix {}", rd, prefix);
199             return;
200         }
201     }
202
203     public synchronized void removeVrfFromDS(String rd) {
204         LOG.debug("Removing vrf table for  rd {}", rd);
205
206         InstanceIdentifierBuilder<VrfTables> idBuilder =
207                 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
208         InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
209
210         BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId);
211
212     }
213 }