2 * Copyright (c) 2016 Cisco Systems, Inc. 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
9 package org.opendaylight.groupbasedpolicy.renderer.vpp.util;
11 import javax.annotation.Nonnull;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
15 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
18 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
19 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.ConfigCommand;
20 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.RoutingCommand;
21 import org.opendaylight.vbd.impl.transaction.VbdNetconfTransaction;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocol;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocolKey;
25 import org.opendaylight.yangtools.yang.binding.DataObject;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
30 import com.google.common.base.Optional;
31 import com.google.common.base.Preconditions;
32 import com.google.common.base.Strings;
33 import com.google.common.util.concurrent.CheckedFuture;
35 public class GbpNetconfTransaction {
37 public static final byte RETRY_COUNT = 3;
38 private static final Logger LOG = LoggerFactory.getLogger(GbpNetconfTransaction.class);
41 * Netconf wrapper for write and delete operation on a Netconf Device
42 * @param mountpoint netconf device
43 * @param iid path for Data to be written to
44 * @param data data to be written
45 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
46 * @param <T> data type
47 * @return true if transaction is successful, false otherwise
49 public static <T extends DataObject> boolean netconfSyncedWrite(@Nonnull final DataBroker mountpoint,
50 @Nonnull final InstanceIdentifier<T> iid, @Nonnull final T data, byte retryCounter) {
51 VbdNetconfTransaction.REENTRANT_LOCK.lock();
52 boolean result = write(mountpoint, iid, data, retryCounter);
53 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
58 * Netconf wrapper method for synced requests for write operation on a Netconf Device
59 * @param mountpoint netconf device
60 * @param command config command that needs to be executed
61 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
62 * @return true if transaction is successful, false otherwise
64 public static boolean netconfSyncedWrite(@Nonnull final DataBroker mountpoint, @Nonnull final ConfigCommand command,
66 VbdNetconfTransaction.REENTRANT_LOCK.lock();
67 boolean result = write(mountpoint, command, retryCounter);
68 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
73 * Netconf wrapper method for synced requests for write operation on a Netconf Device
74 * @param mountpoint netconf device
75 * @param command routing command that needs to be executed
76 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
77 * @return true if transaction is successful, false otherwise
79 public static boolean netconfSyncedWrite(@Nonnull final DataBroker mountpoint, @Nonnull final RoutingCommand command,
81 VbdNetconfTransaction.REENTRANT_LOCK.lock();
82 boolean result = write(mountpoint, command, retryCounter);
83 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
88 * Netconf wrapper method for synced requests for delete operation on a Netconf Device
89 * @param mountpoint netconf device
90 * @param iid path for Data to be written to
91 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
92 * @param <T> data type
93 * @return true if transaction is successful, false otherwise
95 public static <T extends DataObject> boolean netconfSyncedDelete(@Nonnull final DataBroker mountpoint,
96 @Nonnull final InstanceIdentifier<T> iid, byte retryCounter) {
97 VbdNetconfTransaction.REENTRANT_LOCK.lock();
98 boolean result = deleteIfExists(mountpoint, iid, retryCounter);
99 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
104 * Netconf wrapper method for synced requests for delete operation on a Netconf Device
105 * @param mountpoint netconf device
106 * @param command config command that needs to be executed
107 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
108 * @return true if transaction is successful, false otherwise
110 public static boolean netconfSyncedDelete(@Nonnull final DataBroker mountpoint,
111 @Nonnull final ConfigCommand command, byte retryCounter) {
112 VbdNetconfTransaction.REENTRANT_LOCK.lock();
113 boolean result = deleteIfExists(mountpoint, command, retryCounter);
114 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
119 * Netconf wrapper method for synced requests for delete operation on a Netconf Device
120 * @param mountpoint netconf device
121 * @param command routing command that needs to be executed
122 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
123 * @return true if transaction is successful, false otherwise
125 public static boolean netconfSyncedDelete(@Nonnull final DataBroker mountpoint,
126 @Nonnull final RoutingCommand command, byte retryCounter) {
127 VbdNetconfTransaction.REENTRANT_LOCK.lock();
128 boolean result = deleteIfExists(mountpoint, command, retryCounter);
129 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
134 * Use {@link ConfigCommand} to put data into netconf transaction and submit. Transaction is restarted if failed
136 * @param mountpoint to access remote device
137 * @param command config command with data, datastore type and iid
138 * @param retryCounter number of attempts
139 * @return true if transaction is successful, false otherwise
141 private static boolean write(final DataBroker mountpoint, final ConfigCommand command, byte retryCounter) {
142 LOG.trace("Netconf WRITE transaction started. RetryCounter: {}", retryCounter);
143 Preconditions.checkNotNull(mountpoint);
144 final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
146 command.execute(rwTx);
147 final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
149 LOG.trace("Netconf WRITE transaction done for command {}", command);
151 } catch (Exception e) {
153 if (retryCounter > 0) {
154 LOG.warn("Netconf WRITE transaction failed to {}. Restarting transaction ... ", e.getMessage());
155 return write(mountpoint, command, --retryCounter);
157 LOG.warn("Netconf WRITE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
164 * Use {@link RoutingCommand} to put data into netconf transaction and submit. Transaction is restarted if failed
166 * @param mountpoint to access remote device
167 * @param command routing command with data, datastore type and iid
168 * @param retryCounter number of attempts
169 * @return true if transaction is successful, false otherwise
171 private static boolean write(final DataBroker mountpoint, final RoutingCommand command, byte retryCounter) {
172 LOG.trace("Netconf WRITE transaction started. RetryCounter: {}", retryCounter);
173 Preconditions.checkNotNull(mountpoint);
174 final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
176 command.execute(rwTx);
177 final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
179 LOG.trace("Netconf WRITE transaction done for command {}", command);
181 } catch (Exception e) {
183 if (retryCounter > 0) {
184 LOG.warn("Netconf WRITE transaction failed to {}. Restarting transaction ... ", e.getMessage());
185 return write(mountpoint, command, --retryCounter);
187 LOG.warn("Netconf WRITE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
194 * Write data to remote device. Transaction is restarted if failed
196 * @param mountpoint to access remote device
197 * @param iid data identifier
198 * @param data to write
199 * @param retryCounter number of attempts
200 * @param <T> generic data type. Has to be child of {@link DataObject}
201 * @return true if transaction is successful, false otherwise
203 private static <T extends DataObject> boolean write(final DataBroker mountpoint, final InstanceIdentifier<T> iid,
204 final T data, byte retryCounter) {
205 LOG.trace("Netconf WRITE transaction started. RetryCounter: {}", retryCounter);
206 Preconditions.checkNotNull(mountpoint);
207 final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
209 rwTx.put(LogicalDatastoreType.CONFIGURATION, iid, data, true);
210 final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
212 LOG.trace("Netconf WRITE transaction done for {}", iid);
214 } catch (Exception e) {
216 if (retryCounter > 0) {
217 LOG.warn("Netconf WRITE transaction failed to {}. Restarting transaction ... ", e.getMessage());
218 return write(mountpoint, iid, data, --retryCounter);
220 LOG.warn("Netconf WRITE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
227 * Read data from remote device. Transaction is restarted if failed.
229 * @param mountpoint to access remote device
230 * @param datastoreType {@link LogicalDatastoreType}
231 * @param iid data identifier
232 * @param retryCounter number of attempts
233 * @param <T> generic data type. Has to be child of {@link DataObject}
234 * @return optional data object if successful, {@link Optional#absent()} if failed
236 public static synchronized <T extends DataObject> Optional<T> read(final DataBroker mountpoint,
237 final LogicalDatastoreType datastoreType, final InstanceIdentifier<T> iid, byte retryCounter) {
238 LOG.trace("Netconf READ transaction started. RetryCounter: {}", retryCounter);
239 Preconditions.checkNotNull(mountpoint);
240 final ReadOnlyTransaction rTx = mountpoint.newReadOnlyTransaction();
243 final CheckedFuture<Optional<T>, ReadFailedException> futureData =
244 rTx.read(datastoreType, iid);
245 data = futureData.get();
246 LOG.trace("Netconf READ transaction done. Data present: {}", data.isPresent());
248 } catch (Exception e) {
250 if (retryCounter > 0) {
251 LOG.warn("Netconf READ transaction failed to {}. Restarting transaction ... ", e.getMessage());
253 return read(mountpoint, datastoreType, iid, --retryCounter);
255 LOG.warn("Netconf READ transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
256 return Optional.absent();
262 * Remove data from remote device using {@link ConfigCommand}
264 * @param mountpoint to access remote device
265 * @param command config command with data, datastore type and iid
266 * @param retryCounter number of attempts
267 * @return true if transaction is successful, false otherwise
269 private static boolean deleteIfExists(final DataBroker mountpoint, final ConfigCommand command, byte retryCounter) {
270 Preconditions.checkNotNull(mountpoint);
271 InstanceIdentifier<Interface> iid = VppIidFactory.getInterfaceIID(command.getInterfaceBuilder().getKey());
272 return deleteIfExists(mountpoint, iid, retryCounter);
276 * Remove data from remote device using {@link ConfigCommand}
278 * @param mountpoint to access remote device
279 * @param command config command with data, datastore type and iid
280 * @param retryCounter number of attempts
281 * @return true if transaction is successful, false otherwise
283 private static boolean deleteIfExists(final DataBroker mountpoint, final RoutingCommand command,
285 Preconditions.checkNotNull(mountpoint);
286 String routerProtocol = command.getRouterProtocol();
287 if (Strings.isNullOrEmpty(routerProtocol)) {
288 routerProtocol = "learned-protocol-0";
290 InstanceIdentifier<RoutingProtocol> iid =
291 VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(routerProtocol));
292 return deleteIfExists(mountpoint, iid, retryCounter);
296 * Remove data from remote device. Data presence is verified before removal. Transaction is restarted if failed.
298 * @param mountpoint to access remote device
299 * @param iid data identifier
300 * @param retryCounter number of attempts
301 * @param <T> generic data type. Has to be child of {@link DataObject}
302 * @return true if transaction is successful, false otherwise
304 private static <T extends DataObject> boolean deleteIfExists(final DataBroker mountpoint,
305 final InstanceIdentifier<T> iid, byte retryCounter) {
306 LOG.trace("Netconf DELETE transaction started. Data will be read at first. RetryCounter: {}", retryCounter);
307 Preconditions.checkNotNull(mountpoint);
308 final Optional<T> optionalObject = read(mountpoint, LogicalDatastoreType.CONFIGURATION, iid, RETRY_COUNT);
309 if (!optionalObject.isPresent()) {
310 LOG.warn("Netconf DELETE transaction aborted. Data to remove are not present or cannot be read. Iid: {}",
312 // Return true, this state is not considered as an error
315 final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
317 rwTx.delete(LogicalDatastoreType.CONFIGURATION, iid);
318 final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
320 LOG.trace("Netconf DELETE transaction done for {}", iid);
322 } catch (Exception e) {
324 if (retryCounter > 0) {
325 LOG.warn("Netconf DELETE transaction failed to {}. Restarting transaction ... ", e.getMessage());
326 return deleteIfExists(mountpoint, iid, --retryCounter);
328 LOG.warn("Netconf DELETE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);