Switch to JDT annotations for Nullable and NonNull
[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 com.google.common.base.Optional;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.List;
14 import javax.inject.Inject;
15 import javax.inject.Singleton;
16 import org.eclipse.jdt.annotation.Nullable;
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.controller.md.sal.common.api.data.TransactionCommitFailedException;
21 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PortOpData;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.SubnetOpData;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpn;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpnBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpnKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfaces;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfacesBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfacesKey;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
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, BigInteger 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 (ReadFailedException 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, BigInteger 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 (ReadFailedException e) {
107             LOG.error("removeDpnFromSubnet: Failed to read data store for subnet {} dpn {}", subnetId, dpnId);
108         }
109     }
110
111     public SubnetToDpn addInterfaceToDpn(Uuid subnetId, BigInteger 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 = subDpnBuilder.getVpnInterfaces();
131             VpnInterfaces vpnIntfs =
132                 new VpnInterfacesBuilder().withKey(new VpnInterfacesKey(intfName)).setInterfaceName(intfName).build();
133             vpnIntfList.add(vpnIntfs);
134             subDpnBuilder.setVpnInterfaces(vpnIntfList);
135             subDpn = subDpnBuilder.build();
136             SingleTransactionDataBroker.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId, subDpn,
137                     VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
138             LOG.info("addInterfaceToDpn: Created SubnetToDpn entry for subnet {} with DPNId {} intfName {}",
139                     subnetId.getValue(), dpnId, intfName);
140         } catch (TransactionCommitFailedException ex) {
141             LOG.error("addInterfaceToDpn: Addition of Interface {} for SubnetToDpn on subnet {} with DPN {} failed",
142                     intfName, subnetId.getValue(), dpnId, ex);
143         } catch (ReadFailedException e) {
144             LOG.error("addInterfaceToDpn: Failed to read data store for interface {} subnet {} dpn {}", intfName,
145                     subnetId, dpnId);
146         }
147         return subDpn;
148     }
149
150     public void addPortOpDataEntry(String intfName, Uuid subnetId, @Nullable BigInteger dpnId) {
151         try {
152             // Add to PortOpData as well.
153             PortOpDataEntryBuilder portOpBuilder = null;
154             PortOpDataEntry portOpEntry = null;
155             InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
156                 InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
157                     new PortOpDataEntryKey(intfName)).build();
158             Optional<PortOpDataEntry> optionalPortOp = SingleTransactionDataBroker.syncReadOptional(broker,
159                     LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
160             if (!optionalPortOp.isPresent()) {
161                 // Create PortOpDataEntry only if not present
162                 portOpBuilder =
163                     new PortOpDataEntryBuilder().withKey(new PortOpDataEntryKey(intfName)).setPortId(intfName);
164                 List<Uuid> listSubnet = new ArrayList<>();
165                 listSubnet.add(subnetId);
166                 portOpBuilder.setSubnetIds(listSubnet);
167             } else {
168                 List<Uuid> listSubnet = optionalPortOp.get().getSubnetIds();
169                 portOpBuilder = new PortOpDataEntryBuilder(optionalPortOp.get());
170                 if (listSubnet == null) {
171                     listSubnet = new ArrayList<>();
172                 }
173                 if (!listSubnet.contains(subnetId)) {
174                     listSubnet.add(subnetId);
175                 }
176                 portOpBuilder.setSubnetIds(listSubnet);
177             }
178             if (dpnId != null && !dpnId.equals(BigInteger.ZERO)) {
179                 portOpBuilder.setDpnId(dpnId);
180             }
181             portOpEntry = portOpBuilder.build();
182             SingleTransactionDataBroker.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier,
183                 portOpEntry, VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
184             LOG.info("addPortOpDataEntry: Created PortOpData entry for port {} with DPNId {} subnetId {}",
185                      intfName, dpnId, subnetId.getValue());
186         } catch (TransactionCommitFailedException ex) {
187             LOG.error("addPortOpDataEntry: Addition of Interface {} for SubnetToDpn on subnet {} with DPN {} failed",
188                     intfName, subnetId.getValue(), dpnId, ex);
189         } catch (ReadFailedException e) {
190             LOG.error("addPortOpDataEntry: Failed to read from data store for interface {} subnet {} dpn {}",
191                     intfName, subnetId, dpnId);
192         }
193     }
194
195     public boolean removeInterfaceFromDpn(Uuid subnetId, BigInteger dpnId, String intfName) {
196         boolean dpnRemoved = false;
197         try {
198             InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier =
199                 InstanceIdentifier.builder(SubnetOpData.class).child(SubnetOpDataEntry.class,
200                     new SubnetOpDataEntryKey(subnetId)).build();
201             InstanceIdentifier<SubnetToDpn> dpnOpId =
202                 subOpIdentifier.child(SubnetToDpn.class, new SubnetToDpnKey(dpnId));
203             Optional<SubnetToDpn> optionalSubDpn = SingleTransactionDataBroker.syncReadOptional(broker,
204                     LogicalDatastoreType.OPERATIONAL, dpnOpId);
205             if (!optionalSubDpn.isPresent()) {
206                 LOG.debug("removeInterfaceFromDpn: Cannot delete, SubnetToDpn for intf {} subnet {} DPN {}"
207                         + " not available in datastore", intfName, subnetId.getValue(), dpnId);
208                 return false;
209             }
210
211             SubnetToDpnBuilder subDpnBuilder = new SubnetToDpnBuilder(optionalSubDpn.get());
212             List<VpnInterfaces> vpnIntfList = subDpnBuilder.getVpnInterfaces();
213             VpnInterfaces vpnIntfs =
214                 new VpnInterfacesBuilder().withKey(new VpnInterfacesKey(intfName)).setInterfaceName(intfName).build();
215             vpnIntfList.remove(vpnIntfs);
216             if (vpnIntfList.isEmpty()) {
217                 // Remove the DPN as well
218                 removeDpnFromSubnet(subnetId, dpnId);
219                 dpnRemoved = true;
220             } else {
221                 subDpnBuilder.setVpnInterfaces(vpnIntfList);
222                 SingleTransactionDataBroker.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId,
223                     subDpnBuilder.build(), VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
224             }
225             LOG.info("removeInterfaceFromDpn: Removed interface {} from sunbet {} dpn {}",
226                     intfName, subnetId.getValue(), dpnId);
227         } catch (TransactionCommitFailedException ex) {
228             LOG.error("removeInterfaceFromDpn: Deletion of Interface {} for SubnetToDpn on subnet {}"
229                     + " with DPN {} failed", intfName, subnetId.getValue(), dpnId, ex);
230         } catch (ReadFailedException e) {
231             LOG.error("removeInterfaceFromDpn: Failed to read data store for interface {} subnet {} dpn {}",
232                     intfName, subnetId, dpnId);
233         }
234         return dpnRemoved;
235     }
236
237     public PortOpDataEntry removePortOpDataEntry(String intfName, Uuid subnetId) {
238         // Remove PortOpData and return out
239         InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
240                 InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
241                         new PortOpDataEntryKey(intfName)).build();
242         PortOpDataEntry portOpEntry = null;
243         try {
244             Optional<PortOpDataEntry> optionalPortOp = SingleTransactionDataBroker.syncReadOptional(broker,
245                     LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
246             if (!optionalPortOp.isPresent()) {
247                 LOG.info("removePortOpDataEntry: Cannot delete, portOp for port {} is not available in datastore",
248                         intfName);
249             } else {
250                 portOpEntry = optionalPortOp.get();
251                 List<Uuid> listSubnet = portOpEntry.getSubnetIds();
252                 if (listSubnet == null) {
253                     listSubnet = new ArrayList<>();
254                 }
255                 if (subnetId != null && listSubnet.contains(subnetId)) {
256                     listSubnet.remove(subnetId);
257                 }
258                 if (listSubnet.isEmpty() || subnetId == null) {
259                     SingleTransactionDataBroker.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier,
260                             VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
261                     LOG.info("removePortOpDataEntry: Deleted portOpData entry for port {}", intfName);
262                 } else {
263                     PortOpDataEntryBuilder portOpBuilder = null;
264                     portOpBuilder = new PortOpDataEntryBuilder(portOpEntry);
265                     portOpBuilder.setSubnetIds(listSubnet);
266                     SingleTransactionDataBroker.syncWrite(broker, LogicalDatastoreType.OPERATIONAL,
267                             portOpIdentifier, portOpEntry, VpnUtil.SINGLE_TRANSACTION_BROKER_NO_RETRY);
268                     LOG.info("removePortOpDataEntry: Updated PortOpData entry for port {} with removing"
269                             + " subnetId {}", intfName, subnetId.getValue());
270                     portOpEntry = null;
271                 }
272             }
273         } catch (ReadFailedException e) {
274             LOG.error("removePortOpDataEntry: Failed to read data store for interface {} subnet {}", intfName,
275                     subnetId);
276         } catch (TransactionCommitFailedException e) {
277             LOG.error("removePortOpDataEntry: Failed to commit to data store for interface {} subnet {}", intfName,
278                     subnetId);
279         }
280         return portOpEntry;
281     }
282
283     public PortOpDataEntry getPortOpDataEntry(String intfName) {
284         PortOpDataEntry portOpDataEntry = null;
285         try {
286             // Remove PortOpData and return out
287             InstanceIdentifier<PortOpDataEntry> portOpIdentifier =
288                     InstanceIdentifier.builder(PortOpData.class).child(PortOpDataEntry.class,
289                             new PortOpDataEntryKey(intfName)).build();
290             Optional<PortOpDataEntry> optionalPortOp = SingleTransactionDataBroker.syncReadOptional(broker,
291                     LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
292             if (optionalPortOp.isPresent()) {
293                 portOpDataEntry = optionalPortOp.get();
294             }
295         } catch (ReadFailedException e) {
296             LOG.error("getPortOpDataEntry: Failed to read data store for interface {}", intfName);
297         }
298         return portOpDataEntry;
299     }
300 }