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.netvirt.vpnmanager;
10 import java.util.ArrayList;
11 import java.util.List;
12 import java.util.Optional;
13 import java.util.concurrent.ExecutionException;
14 import javax.inject.Inject;
15 import javax.inject.Singleton;
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
18 import org.opendaylight.mdsal.binding.api.DataBroker;
19 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
20 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PortOpData;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.SubnetOpData;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpn;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpnBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpnKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfaces;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfacesBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfacesKey;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.opendaylight.yangtools.yang.common.Uint64;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
41 public class SubnetOpDpnManager {
42 private static final Logger LOG = LoggerFactory.getLogger(SubnetOpDpnManager.class);
44 private final DataBroker broker;
47 public SubnetOpDpnManager(final DataBroker db) {
52 private SubnetToDpn addDpnToSubnet(Uuid subnetId, Uint64 dpnId) {
54 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
55 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
56 new SubnetOpDataEntryKey(subnetId)).build();
57 InstanceIdentifier<SubnetToDpn> dpnOpId =
58 subOpIdentifier.child(SubnetToDpn.class, new SubnetToDpnKey(dpnId));
59 Optional<SubnetToDpn> optionalSubDpn = SingleTransactionDataBroker.syncReadOptional(broker,
60 LogicalDatastoreType.OPERATIONAL, dpnOpId);
61 if (optionalSubDpn.isPresent()) {
62 LOG.error("addDpnToSubnet: Cannot create, SubnetToDpn for subnet {} as DPN {}"
63 + " already seen in datastore", subnetId.getValue(), dpnId);
66 SubnetToDpnBuilder subDpnBuilder = new SubnetToDpnBuilder().withKey(new SubnetToDpnKey(dpnId));
67 List<VpnInterfaces> vpnIntfList = new ArrayList<>();
68 subDpnBuilder.setVpnInterfaces(vpnIntfList);
69 SubnetToDpn subDpn = subDpnBuilder.build();
70 SingleTransactionDataBroker.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId, subDpn,
71 VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
72 LOG.info("addDpnToSubnet: Created SubnetToDpn entry for subnet {} with DPNId {} ", subnetId.getValue(),
75 } catch (TransactionCommitFailedException ex) {
76 LOG.error("addDpnToSubnet: Creation of SubnetToDpn for subnet {} with DpnId {} failed",
77 subnetId.getValue(), dpnId, ex);
78 } catch (InterruptedException | ExecutionException e) {
79 LOG.error("addDpnToSubnet: Failed to read data store for subnet {} dpn {}", subnetId.getValue(),
85 private void removeDpnFromSubnet(Uuid subnetId, Uint64 dpnId) {
87 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
88 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
89 new SubnetOpDataEntryKey(subnetId)).build();
90 InstanceIdentifier<SubnetToDpn> dpnOpId =
91 subOpIdentifier.child(SubnetToDpn.class, new SubnetToDpnKey(dpnId));
92 Optional<SubnetToDpn> optionalSubDpn = SingleTransactionDataBroker.syncReadOptional(broker,
93 LogicalDatastoreType.OPERATIONAL, dpnOpId);
94 if (!optionalSubDpn.isPresent()) {
95 LOG.warn("removeDpnFromSubnet: Cannot delete, SubnetToDpn for subnet {} DPN {} not available"
96 + " in datastore", subnetId.getValue(), dpnId);
99 LOG.trace("removeDpnFromSubnet: Deleting SubnetToDpn entry for subnet {} with DPNId {}",
100 subnetId.getValue(), dpnId);
101 SingleTransactionDataBroker.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId,
102 VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
103 } catch (TransactionCommitFailedException ex) {
104 LOG.error("removeDpnFromSubnet: Deletion of SubnetToDpn for subnet {} with DPN {} failed",
105 subnetId.getValue(), dpnId, ex);
106 } catch (InterruptedException | ExecutionException e) {
107 LOG.error("removeDpnFromSubnet: Failed to read data store for subnet {} dpn {}", subnetId, dpnId);
111 public SubnetToDpn addInterfaceToDpn(Uuid subnetId, Uint64 dpnId, String intfName) {
112 SubnetToDpn subDpn = null;
114 // Create and add SubnetOpDataEntry object for this subnet to the SubnetOpData container
115 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
116 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
117 new SubnetOpDataEntryKey(subnetId)).build();
118 //Please use a synchronize block here as we donot need a cluster-wide lock
119 InstanceIdentifier<SubnetToDpn> dpnOpId =
120 subOpIdentifier.child(SubnetToDpn.class, new SubnetToDpnKey(dpnId));
121 Optional<SubnetToDpn> optionalSubDpn = SingleTransactionDataBroker.syncReadOptional(broker,
122 LogicalDatastoreType.OPERATIONAL, dpnOpId);
123 if (!optionalSubDpn.isPresent()) {
124 // Create a new DPN Entry
125 subDpn = addDpnToSubnet(subnetId, dpnId);
127 subDpn = optionalSubDpn.get();
129 SubnetToDpnBuilder subDpnBuilder = new SubnetToDpnBuilder(subDpn);
130 List<VpnInterfaces> vpnIntfList = new ArrayList<>();
131 vpnIntfList = subDpnBuilder.getVpnInterfaces() != null ? new ArrayList<>(subDpnBuilder.getVpnInterfaces())
134 VpnInterfaces vpnIntfs =
135 new VpnInterfacesBuilder().withKey(new VpnInterfacesKey(intfName)).setInterfaceName(intfName).build();
136 vpnIntfList.add(vpnIntfs);
137 subDpnBuilder.setVpnInterfaces(vpnIntfList);
138 subDpn = subDpnBuilder.build();
139 SingleTransactionDataBroker.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId, subDpn,
140 VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
141 LOG.info("addInterfaceToDpn: Created SubnetToDpn entry for subnet {} with DPNId {} intfName {}",
142 subnetId.getValue(), dpnId, intfName);
143 } catch (TransactionCommitFailedException ex) {
144 LOG.error("addInterfaceToDpn: Addition of Interface {} for SubnetToDpn on subnet {} with DPN {} failed",
145 intfName, subnetId.getValue(), dpnId, ex);
146 } catch (InterruptedException | ExecutionException e) {
147 LOG.error("addInterfaceToDpn: Failed to read data store for interface {} subnet {} dpn {}", intfName,
153 public void addPortOpDataEntry(String intfName, Uuid subnetId, @Nullable Uint64 dpnId) {
155 // Add to PortOpData as well.
156 PortOpDataEntryBuilder portOpBuilder = null;
157 PortOpDataEntry portOpEntry = null;
158 InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
159 InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
160 new PortOpDataEntryKey(intfName)).build();
161 Optional<PortOpDataEntry> optionalPortOp = SingleTransactionDataBroker.syncReadOptional(broker,
162 LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
163 if (!optionalPortOp.isPresent()) {
164 // Create PortOpDataEntry only if not present
166 new PortOpDataEntryBuilder().withKey(new PortOpDataEntryKey(intfName)).setPortId(intfName);
167 List<Uuid> listSubnet = new ArrayList<>();
168 listSubnet.add(subnetId);
169 portOpBuilder.setSubnetIds(listSubnet);
171 PortOpDataEntry portEntry = optionalPortOp.get();
172 List<Uuid> listSubnet = new ArrayList<>();
173 listSubnet = (portEntry.getSubnetIds() != null && !portEntry.getSubnetIds().isEmpty())
174 ? new ArrayList<>(portEntry.getSubnetIds()) : listSubnet;
175 portOpBuilder = new PortOpDataEntryBuilder(optionalPortOp.get());
176 if (listSubnet == null) {
177 listSubnet = new ArrayList<>();
179 if (!listSubnet.contains(subnetId)) {
180 listSubnet.add(subnetId);
182 portOpBuilder.setSubnetIds(listSubnet);
184 if (dpnId != null && !dpnId.equals(Uint64.ZERO)) {
185 portOpBuilder.setDpnId(dpnId);
187 portOpEntry = portOpBuilder.build();
188 SingleTransactionDataBroker.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier,
189 portOpEntry, VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
190 LOG.info("addPortOpDataEntry: Created PortOpData entry for port {} with DPNId {} subnetId {}",
191 intfName, dpnId, subnetId.getValue());
192 } catch (TransactionCommitFailedException ex) {
193 LOG.error("addPortOpDataEntry: Addition of Interface {} for SubnetToDpn on subnet {} with DPN {} failed",
194 intfName, subnetId.getValue(), dpnId, ex);
195 } catch (InterruptedException | ExecutionException e) {
196 LOG.error("addPortOpDataEntry: Failed to read from data store for interface {} subnet {} dpn {}",
197 intfName, subnetId, dpnId);
201 public boolean removeInterfaceFromDpn(Uuid subnetId, Uint64 dpnId, String intfName) {
202 boolean dpnRemoved = false;
204 InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
205 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
206 new SubnetOpDataEntryKey(subnetId)).build();
207 InstanceIdentifier<SubnetToDpn> dpnOpId =
208 subOpIdentifier.child(SubnetToDpn.class, new SubnetToDpnKey(dpnId));
209 Optional<SubnetToDpn> optionalSubDpn = SingleTransactionDataBroker.syncReadOptional(broker,
210 LogicalDatastoreType.OPERATIONAL, dpnOpId);
211 if (!optionalSubDpn.isPresent()) {
212 LOG.debug("removeInterfaceFromDpn: Cannot delete, SubnetToDpn for intf {} subnet {} DPN {}"
213 + " not available in datastore", intfName, subnetId.getValue(), dpnId);
217 SubnetToDpnBuilder subDpnBuilder = new SubnetToDpnBuilder(optionalSubDpn.get());
218 List<VpnInterfaces> vpnIntfList = new ArrayList<>();
219 vpnIntfList = (subDpnBuilder.getVpnInterfaces() != null && !subDpnBuilder.getVpnInterfaces().isEmpty())
220 ? new ArrayList<>(subDpnBuilder.getVpnInterfaces()) : vpnIntfList;
221 VpnInterfaces vpnIntfs =
222 new VpnInterfacesBuilder().withKey(new VpnInterfacesKey(intfName)).setInterfaceName(intfName).build();
223 vpnIntfList.remove(vpnIntfs);
224 if (vpnIntfList.isEmpty()) {
225 // Remove the DPN as well
226 removeDpnFromSubnet(subnetId, dpnId);
229 subDpnBuilder.setVpnInterfaces(vpnIntfList);
230 SingleTransactionDataBroker.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId,
231 subDpnBuilder.build(), VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
233 LOG.info("removeInterfaceFromDpn: Removed interface {} from sunbet {} dpn {}",
234 intfName, subnetId.getValue(), dpnId);
235 } catch (TransactionCommitFailedException ex) {
236 LOG.error("removeInterfaceFromDpn: Deletion of Interface {} for SubnetToDpn on subnet {}"
237 + " with DPN {} failed", intfName, subnetId.getValue(), dpnId, ex);
238 } catch (InterruptedException | ExecutionException e) {
239 LOG.error("removeInterfaceFromDpn: Failed to read data store for interface {} subnet {} dpn {}",
240 intfName, subnetId, dpnId);
245 public PortOpDataEntry removePortOpDataEntry(String intfName, Uuid subnetId) {
246 // Remove PortOpData and return out
247 InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
248 InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
249 new PortOpDataEntryKey(intfName)).build();
250 PortOpDataEntry portOpEntry = null;
252 Optional<PortOpDataEntry> optionalPortOp = SingleTransactionDataBroker.syncReadOptional(broker,
253 LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
254 if (!optionalPortOp.isPresent()) {
255 LOG.info("removePortOpDataEntry: Cannot delete, portOp for port {} is not available in datastore",
258 portOpEntry = optionalPortOp.get();
259 List<Uuid> listSubnet = new ArrayList<>();
260 listSubnet = (portOpEntry.getSubnetIds() != null && !portOpEntry.getSubnetIds().isEmpty())
261 ? new ArrayList<>(portOpEntry.getSubnetIds()) : listSubnet;
262 if (listSubnet == null) {
263 listSubnet = new ArrayList<>();
265 if (subnetId != null && listSubnet.contains(subnetId)) {
266 listSubnet.remove(subnetId);
268 if (listSubnet.isEmpty() || subnetId == null) {
269 SingleTransactionDataBroker.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier,
270 VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
271 LOG.info("removePortOpDataEntry: Deleted portOpData entry for port {}", intfName);
273 PortOpDataEntryBuilder portOpBuilder = null;
274 portOpBuilder = new PortOpDataEntryBuilder(portOpEntry);
275 portOpBuilder.setSubnetIds(listSubnet);
276 SingleTransactionDataBroker.syncWrite(broker, LogicalDatastoreType.OPERATIONAL,
277 portOpIdentifier, portOpEntry, VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
278 LOG.info("removePortOpDataEntry: Updated PortOpData entry for port {} with removing"
279 + " subnetId {}", intfName, subnetId.getValue());
283 } catch (InterruptedException | ExecutionException e) {
284 LOG.error("removePortOpDataEntry: Failed to read data store for interface {} subnet {}", intfName,
286 } catch (TransactionCommitFailedException e) {
287 LOG.error("removePortOpDataEntry: Failed to commit to data store for interface {} subnet {}", intfName,
293 public PortOpDataEntry getPortOpDataEntry(String intfName) {
294 PortOpDataEntry portOpDataEntry = null;
296 // Remove PortOpData and return out
297 InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
298 InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
299 new PortOpDataEntryKey(intfName)).build();
300 Optional<PortOpDataEntry> optionalPortOp = SingleTransactionDataBroker.syncReadOptional(broker,
301 LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
302 if (optionalPortOp.isPresent()) {
303 portOpDataEntry = optionalPortOp.get();
305 } catch (InterruptedException | ExecutionException e) {
306 LOG.error("getPortOpDataEntry: Failed to read data store for interface {}", intfName);
308 return portOpDataEntry;