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.AbstractConfigCommand;
20 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.AbstractInterfaceCommand;
21 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.interfaces.ConfigCommand;
22 import org.opendaylight.vbd.impl.transaction.VbdNetconfTransaction;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
24 import org.opendaylight.yangtools.yang.binding.DataObject;
25 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
29 import com.google.common.base.Optional;
30 import com.google.common.base.Preconditions;
31 import com.google.common.util.concurrent.CheckedFuture;
33 public class GbpNetconfTransaction {
35 public static final byte RETRY_COUNT = 3;
36 private static final Logger LOG = LoggerFactory.getLogger(GbpNetconfTransaction.class);
39 * Netconf wrapper for write and delete operation on a Netconf Device
40 * @param mountpoint netconf device
41 * @param iid path for Data to be written to
42 * @param data data to be written
43 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
44 * @param <T> data type
45 * @return true if transaction is successful, false otherwise
47 public static <T extends DataObject> boolean netconfSyncedWrite(@Nonnull final DataBroker mountpoint,
48 @Nonnull final InstanceIdentifier<T> iid, @Nonnull final T data, byte retryCounter) {
49 VbdNetconfTransaction.REENTRANT_LOCK.lock();
50 boolean result = write(mountpoint, iid, data, retryCounter);
51 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
56 * Netconf wrapper method for synced requests for write operation on a Netconf Device
57 * @param mountpoint netconf device
58 * @param command config command that needs to be executed
59 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
60 * @return true if transaction is successful, false otherwise
62 public static boolean netconfSyncedWrite(@Nonnull final DataBroker mountpoint, @Nonnull final ConfigCommand command,
64 VbdNetconfTransaction.REENTRANT_LOCK.lock();
65 boolean result = write(mountpoint, command, retryCounter);
66 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
71 * Netconf wrapper method for synced requests for delete operation on a Netconf Device
72 * @param mountpoint netconf device
73 * @param iid path for Data to be written to
74 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
75 * @param <T> data type
76 * @return true if transaction is successful, false otherwise
78 public static <T extends DataObject> boolean netconfSyncedDelete(@Nonnull final DataBroker mountpoint,
79 @Nonnull final InstanceIdentifier<T> iid, byte retryCounter) {
80 VbdNetconfTransaction.REENTRANT_LOCK.lock();
81 boolean result = deleteIfExists(mountpoint, iid, retryCounter);
82 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
87 * Netconf wrapper method for synced requests for delete operation on a Netconf Device
88 * @param mountpoint netconf device
89 * @param command config command that needs to be executed
90 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
91 * @return true if transaction is successful, false otherwise
93 public static boolean netconfSyncedDelete(@Nonnull final DataBroker mountpoint,
94 @Nonnull final AbstractInterfaceCommand command, byte retryCounter) {
95 VbdNetconfTransaction.REENTRANT_LOCK.lock();
96 boolean result = deleteIfExists(mountpoint, command, retryCounter);
97 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
102 * Netconf wrapper method for synced requests for delete operation on a Netconf Device
103 * @param mountpoint netconf device
104 * @param command routing command that needs to be executed
105 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
106 * @return true if transaction is successful, false otherwise
108 public static boolean netconfSyncedDelete(@Nonnull final DataBroker mountpoint,
109 @Nonnull final AbstractConfigCommand command, byte retryCounter) {
110 VbdNetconfTransaction.REENTRANT_LOCK.lock();
111 boolean result = deleteIfExists(mountpoint, command, retryCounter);
112 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
117 * Use {@link ConfigCommand} to put data into netconf transaction and submit. Transaction is restarted if failed
119 * @param mountpoint to access remote device
120 * @param command config command with data, datastore type and iid
121 * @param retryCounter number of attempts
122 * @return true if transaction is successful, false otherwise
124 private static boolean write(final DataBroker mountpoint, final ConfigCommand command, byte retryCounter) {
125 LOG.trace("Netconf WRITE transaction started. RetryCounter: {}", retryCounter);
126 Preconditions.checkNotNull(mountpoint);
127 final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
129 command.execute(rwTx);
130 final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
132 LOG.trace("Netconf WRITE transaction done for command {}", command);
134 } catch (Exception e) {
136 if (retryCounter > 0) {
137 LOG.warn("Netconf WRITE transaction failed to {}. Restarting transaction ... ", e.getMessage());
138 return write(mountpoint, command, --retryCounter);
140 LOG.warn("Netconf WRITE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
147 * Write data to remote device. Transaction is restarted if failed
149 * @param mountpoint to access remote device
150 * @param iid data identifier
151 * @param data to write
152 * @param retryCounter number of attempts
153 * @param <T> generic data type. Has to be child of {@link DataObject}
154 * @return true if transaction is successful, false otherwise
156 private static <T extends DataObject> boolean write(final DataBroker mountpoint, final InstanceIdentifier<T> iid,
157 final T data, byte retryCounter) {
158 LOG.trace("Netconf WRITE transaction started. RetryCounter: {}", retryCounter);
159 Preconditions.checkNotNull(mountpoint);
160 final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
162 rwTx.put(LogicalDatastoreType.CONFIGURATION, iid, data, true);
163 final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
165 LOG.trace("Netconf WRITE transaction done for {}", iid);
167 } catch (Exception e) {
169 if (retryCounter > 0) {
170 LOG.warn("Netconf WRITE transaction failed to {}. Restarting transaction ... ", e.getMessage());
171 return write(mountpoint, iid, data, --retryCounter);
173 LOG.warn("Netconf WRITE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
180 * Read data from remote device. Transaction is restarted if failed.
182 * @param mountpoint to access remote device
183 * @param datastoreType {@link LogicalDatastoreType}
184 * @param iid data identifier
185 * @param retryCounter number of attempts
186 * @param <T> generic data type. Has to be child of {@link DataObject}
187 * @return optional data object if successful, {@link Optional#absent()} if failed
189 public static synchronized <T extends DataObject> Optional<T> read(final DataBroker mountpoint,
190 final LogicalDatastoreType datastoreType, final InstanceIdentifier<T> iid, byte retryCounter) {
191 LOG.trace("Netconf READ transaction started. RetryCounter: {}", retryCounter);
192 Preconditions.checkNotNull(mountpoint);
193 final ReadOnlyTransaction rTx = mountpoint.newReadOnlyTransaction();
196 final CheckedFuture<Optional<T>, ReadFailedException> futureData =
197 rTx.read(datastoreType, iid);
198 data = futureData.get();
199 LOG.trace("Netconf READ transaction done. Data present: {}", data.isPresent());
201 } catch (Exception e) {
203 if (retryCounter > 0) {
204 LOG.warn("Netconf READ transaction failed to {}. Restarting transaction ... ", e.getMessage());
206 return read(mountpoint, datastoreType, iid, --retryCounter);
208 LOG.warn("Netconf READ transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
209 return Optional.absent();
215 * Remove data from remote device using {@link ConfigCommand}
217 * @param mountpoint to access remote device
218 * @param command config command with data, datastore type and iid
219 * @param retryCounter number of attempts
220 * @return true if transaction is successful, false otherwise
222 private static boolean deleteIfExists(final DataBroker mountpoint,
223 final AbstractInterfaceCommand command,
225 Preconditions.checkNotNull(mountpoint);
226 InstanceIdentifier<Interface> iid = VppIidFactory.getInterfaceIID(command.getInterfaceBuilder().getKey());
227 return deleteIfExists(mountpoint, iid, retryCounter);
231 * Remove data from remote device using {@link ConfigCommand}
233 * @param mountpoint to access remote device
234 * @param command config command with data, datastore type and iid
235 * @param retryCounter number of attempts
236 * @return true if transaction is successful, false otherwise
238 private static boolean deleteIfExists(final DataBroker mountpoint, final AbstractConfigCommand command,
240 Preconditions.checkNotNull(mountpoint);
242 return deleteIfExists(mountpoint, command.getIid(), retryCounter);
246 * Remove data from remote device. Data presence is verified before removal. Transaction is restarted if failed.
248 * @param mountpoint to access remote device
249 * @param iid data identifier
250 * @param retryCounter number of attempts
251 * @param <T> generic data type. Has to be child of {@link DataObject}
252 * @return true if transaction is successful, false otherwise
254 private static <T extends DataObject> boolean deleteIfExists(final DataBroker mountpoint,
255 final InstanceIdentifier<T> iid, byte retryCounter) {
256 LOG.trace("Netconf DELETE transaction started. Data will be read at first. RetryCounter: {}", retryCounter);
257 Preconditions.checkNotNull(mountpoint);
258 final Optional<T> optionalObject = read(mountpoint, LogicalDatastoreType.CONFIGURATION, iid, RETRY_COUNT);
259 if (!optionalObject.isPresent()) {
260 LOG.warn("Netconf DELETE transaction aborted. Data to remove are not present or cannot be read. Iid: {}",
262 // Return true, this state is not considered as an error
265 final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
267 rwTx.delete(LogicalDatastoreType.CONFIGURATION, iid);
268 final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
270 LOG.trace("Netconf DELETE transaction done for {}", iid);
272 } catch (Exception e) {
274 if (retryCounter > 0) {
275 LOG.warn("Netconf DELETE transaction failed to {}. Restarting transaction ... ", e.getMessage());
276 return deleteIfExists(mountpoint, iid, --retryCounter);
278 LOG.warn("Netconf DELETE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);