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.vbd.impl.transaction.VbdNetconfTransaction;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
22 import org.opendaylight.yangtools.yang.binding.DataObject;
23 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
27 import com.google.common.base.Optional;
28 import com.google.common.base.Preconditions;
29 import com.google.common.util.concurrent.CheckedFuture;
31 public class GbpNetconfTransaction {
33 public static final byte RETRY_COUNT = 3;
34 private static final Logger LOG = LoggerFactory.getLogger(GbpNetconfTransaction.class);
37 * Netconf wrapper for write and delete operation on a Netconf Device
38 * @param mountpoint netconf device
39 * @param iid path for Data to be written to
40 * @param data data to be written
41 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
42 * @param <T> data type
43 * @return true if transaction is successful, false otherwise
45 public static <T extends DataObject> boolean netconfSyncedWrite(@Nonnull final DataBroker mountpoint,
46 @Nonnull final InstanceIdentifier<T> iid, @Nonnull final T data, byte retryCounter) {
47 VbdNetconfTransaction.REENTRANT_LOCK.lock();
48 boolean result = write(mountpoint, iid, data, retryCounter);
49 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
54 * Netconf wrapper method for synced requests for write operation on a Netconf Device
55 * @param mountpoint netconf device
56 * @param command config command that needs to be executed
57 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
58 * @return true if transaction is successful, false otherwise
60 public static boolean netconfSyncedWrite(@Nonnull final DataBroker mountpoint, @Nonnull final ConfigCommand command,
62 VbdNetconfTransaction.REENTRANT_LOCK.lock();
63 boolean result = write(mountpoint, command, retryCounter);
64 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
69 * Netconf wrapper method for synced requests for delete operation on a Netconf Device
70 * @param mountpoint netconf device
71 * @param iid path for Data to be written to
72 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
73 * @param <T> data type
74 * @return true if transaction is successful, false otherwise
76 public static <T extends DataObject> boolean netconfSyncedDelete(@Nonnull final DataBroker mountpoint,
77 @Nonnull final InstanceIdentifier<T> iid, byte retryCounter) {
78 VbdNetconfTransaction.REENTRANT_LOCK.lock();
79 boolean result = deleteIfExists(mountpoint, iid, retryCounter);
80 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
85 * Netconf wrapper method for synced requests for delete operation on a Netconf Device
86 * @param mountpoint netconf device
87 * @param command config command that needs to be executed
88 * @param retryCounter retry counter, will repeat the operation for specified amount of times if transaction fails
89 * @return true if transaction is successful, false otherwise
91 public static boolean netconfSyncedDelete(@Nonnull final DataBroker mountpoint,
92 @Nonnull final ConfigCommand command, byte retryCounter) {
93 VbdNetconfTransaction.REENTRANT_LOCK.lock();
94 boolean result = deleteIfExists(mountpoint, command, retryCounter);
95 VbdNetconfTransaction.REENTRANT_LOCK.unlock();
101 * Use {@link ConfigCommand} to put data into netconf transaction and submit. Transaction is restarted if failed
103 * @param mountpoint to access remote device
104 * @param command config command with data, datastore type and iid
105 * @param retryCounter number of attempts
106 * @return true if transaction is successful, false otherwise
108 private static boolean write(final DataBroker mountpoint, final ConfigCommand command, byte retryCounter) {
109 LOG.trace("Netconf WRITE transaction started. RetryCounter: {}", retryCounter);
110 Preconditions.checkNotNull(mountpoint);
111 final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
113 command.execute(rwTx);
114 final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
116 LOG.trace("Netconf WRITE transaction done for command {}", command);
118 } catch (Exception e) {
120 if (retryCounter > 0) {
121 LOG.warn("Netconf WRITE transaction failed to {}. Restarting transaction ... ", e.getMessage());
122 return write(mountpoint, command, --retryCounter);
124 LOG.warn("Netconf WRITE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
131 * Write data to remote device. Transaction is restarted if failed
133 * @param mountpoint to access remote device
134 * @param iid data identifier
135 * @param data to write
136 * @param retryCounter number of attempts
137 * @param <T> generic data type. Has to be child of {@link DataObject}
138 * @return true if transaction is successful, false otherwise
140 private static <T extends DataObject> boolean write(final DataBroker mountpoint,
141 final InstanceIdentifier<T> iid,
144 LOG.trace("Netconf WRITE transaction started. RetryCounter: {}", retryCounter);
145 Preconditions.checkNotNull(mountpoint);
146 final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
148 rwTx.put(LogicalDatastoreType.CONFIGURATION, iid, data, true);
149 final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
151 LOG.trace("Netconf WRITE transaction done for {}", iid);
153 } catch (Exception e) {
155 if (retryCounter > 0) {
156 LOG.warn("Netconf WRITE transaction failed to {}. Restarting transaction ... ", e.getMessage());
157 return write(mountpoint, iid, data, --retryCounter);
159 LOG.warn("Netconf WRITE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
166 * Read data from remote device. Transaction is restarted if failed.
168 * @param mountpoint to access remote device
169 * @param datastoreType {@link LogicalDatastoreType}
170 * @param iid data identifier
171 * @param retryCounter number of attempts
172 * @param <T> generic data type. Has to be child of {@link DataObject}
173 * @return optional data object if successful, {@link Optional#absent()} if failed
175 public static synchronized <T extends DataObject> Optional<T> read(final DataBroker mountpoint,
176 final LogicalDatastoreType datastoreType,
177 final InstanceIdentifier<T> iid,
179 LOG.trace("Netconf READ transaction started. RetryCounter: {}", retryCounter);
180 Preconditions.checkNotNull(mountpoint);
181 final ReadOnlyTransaction rTx = mountpoint.newReadOnlyTransaction();
184 final CheckedFuture<Optional<T>, ReadFailedException> futureData =
185 rTx.read(datastoreType, iid);
186 data = futureData.get();
187 LOG.trace("Netconf READ transaction done. Data present: {}", data.isPresent());
189 } catch (Exception e) {
191 if (retryCounter > 0) {
192 LOG.warn("Netconf READ transaction failed to {}. Restarting transaction ... ", e.getMessage());
194 return read(mountpoint, datastoreType, iid, --retryCounter);
196 LOG.warn("Netconf READ transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
197 return Optional.absent();
203 * Remove data from remote device using {@link ConfigCommand}
205 * @param mountpoint to access remote device
206 * @param command config command with data, datastore type and iid
207 * @param retryCounter number of attempts
208 * @return true if transaction is successful, false otherwise
210 private static boolean deleteIfExists(final DataBroker mountpoint, final ConfigCommand command,
212 Preconditions.checkNotNull(mountpoint);
213 InstanceIdentifier<Interface> iid = VppIidFactory.getInterfaceIID(command.getInterfaceBuilder().getKey());
214 return deleteIfExists(mountpoint, iid, retryCounter);
218 * Remove data from remote device. Data presence is verified before removal. Transaction is restarted if failed.
220 * @param mountpoint to access remote device
221 * @param iid data identifier
222 * @param retryCounter number of attempts
223 * @param <T> generic data type. Has to be child of {@link DataObject}
224 * @return true if transaction is successful, false otherwise
226 private static <T extends DataObject> boolean deleteIfExists(final DataBroker mountpoint,
227 final InstanceIdentifier<T> iid,
229 LOG.trace("Netconf DELETE transaction started. Data will be read at first. RetryCounter: {}", retryCounter);
230 Preconditions.checkNotNull(mountpoint);
231 final Optional<T> optionalObject = read(mountpoint, LogicalDatastoreType.CONFIGURATION, iid, RETRY_COUNT);
232 if (!optionalObject.isPresent()) {
233 LOG.warn("Netconf DELETE transaction aborted. Data to remove are not present or cannot be read. Iid: {}",
235 // Return true, this state is not considered as an error
238 final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
240 rwTx.delete(LogicalDatastoreType.CONFIGURATION, iid);
241 final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
243 LOG.trace("Netconf DELETE transaction done for {}", iid);
245 } catch (Exception e) {
247 if (retryCounter > 0) {
248 LOG.warn("Netconf DELETE transaction failed to {}. Restarting transaction ... ", e.getMessage());
249 return deleteIfExists(mountpoint, iid, --retryCounter);
251 LOG.warn("Netconf DELETE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);