NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / SubnetOpDpnManager.java
1 /*
2  * Copyright (c) 2016 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 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;
39
40 @Singleton
41 public class SubnetOpDpnManager {
42     private static final Logger LOG = LoggerFactory.getLogger(SubnetOpDpnManager.class);
43
44     private final DataBroker broker;
45
46     @Inject
47     public SubnetOpDpnManager(final DataBroker db) {
48         broker = db;
49     }
50
51     @Nullable
52     private SubnetToDpn addDpnToSubnet(Uuid subnetId, Uint64 dpnId) {
53         try {
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);
64                 return null;
65             }
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(),
73                     dpnId);
74             return subDpn;
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(),
80                     dpnId);
81         }
82         return null;
83     }
84
85     private void removeDpnFromSubnet(Uuid subnetId, Uint64 dpnId) {
86         try {
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);
97                 return;
98             }
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);
108         }
109     }
110
111     public SubnetToDpn addInterfaceToDpn(Uuid subnetId, Uint64 dpnId, String intfName) {
112         SubnetToDpn subDpn = null;
113         try {
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);
126             } else {
127                 subDpn = optionalSubDpn.get();
128             }
129             SubnetToDpnBuilder subDpnBuilder = new SubnetToDpnBuilder(subDpn);
130             List<VpnInterfaces> vpnIntfList = new ArrayList<>();
131             vpnIntfList = subDpnBuilder.getVpnInterfaces() != null ? new ArrayList<>(subDpnBuilder.getVpnInterfaces())
132                     : vpnIntfList;
133
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,
148                     subnetId, dpnId);
149         }
150         return subDpn;
151     }
152
153     public void addPortOpDataEntry(String intfName, Uuid subnetId, @Nullable Uint64 dpnId) {
154         try {
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
165                 portOpBuilder =
166                     new PortOpDataEntryBuilder().withKey(new PortOpDataEntryKey(intfName)).setPortId(intfName);
167                 List<Uuid> listSubnet = new ArrayList<>();
168                 listSubnet.add(subnetId);
169                 portOpBuilder.setSubnetIds(listSubnet);
170             } else {
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<>();
178                 }
179                 if (!listSubnet.contains(subnetId)) {
180                     listSubnet.add(subnetId);
181                 }
182                 portOpBuilder.setSubnetIds(listSubnet);
183             }
184             if (dpnId != null && !dpnId.equals(Uint64.ZERO)) {
185                 portOpBuilder.setDpnId(dpnId);
186             }
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);
198         }
199     }
200
201     public boolean removeInterfaceFromDpn(Uuid subnetId, Uint64 dpnId, String intfName) {
202         boolean dpnRemoved = false;
203         try {
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);
214                 return false;
215             }
216
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);
227                 dpnRemoved = true;
228             } else {
229                 subDpnBuilder.setVpnInterfaces(vpnIntfList);
230                 SingleTransactionDataBroker.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId,
231                     subDpnBuilder.build(), VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
232             }
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);
241         }
242         return dpnRemoved;
243     }
244
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;
251         try {
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",
256                         intfName);
257             } else {
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<>();
264                 }
265                 if (subnetId != null && listSubnet.contains(subnetId)) {
266                     listSubnet.remove(subnetId);
267                 }
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);
272                 } else {
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());
280                     portOpEntry = null;
281                 }
282             }
283         } catch (InterruptedException | ExecutionException e) {
284             LOG.error("removePortOpDataEntry: Failed to read data store for interface {} subnet {}", intfName,
285                     subnetId);
286         } catch (TransactionCommitFailedException e) {
287             LOG.error("removePortOpDataEntry: Failed to commit to data store for interface {} subnet {}", intfName,
288                     subnetId);
289         }
290         return portOpEntry;
291     }
292
293     public PortOpDataEntry getPortOpDataEntry(String intfName) {
294         PortOpDataEntry portOpDataEntry = null;
295         try {
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();
304             }
305         } catch (InterruptedException | ExecutionException e) {
306             LOG.error("getPortOpDataEntry: Failed to read data store for interface {}", intfName);
307         }
308         return portOpDataEntry;
309     }
310 }