private ListenableFuture<Void> deleteIfaceOnVpp(ConfigCommand deleteIfaceWithoutBdCommand,
DataBroker vppDataBroker, VppEndpoint vppEndpoint, InstanceIdentifier<?> vppNodeIid) {
- final boolean transactionState = GbpNetconfTransaction.delete(vppDataBroker, deleteIfaceWithoutBdCommand,
+ final boolean transactionState = GbpNetconfTransaction.deleteIfExists(vppDataBroker, deleteIfaceWithoutBdCommand,
GbpNetconfTransaction.RETRY_COUNT);
if (transactionState) {
LOG.debug("Delete interface on VPP command was successful: VPP: {} Command: {}", vppNodeIid,
LOG.warn("Interface already not in bridge domain {} ", ifaceKey);
return Futures.immediateFuture(null);
}
- final boolean transactionState = GbpNetconfTransaction.delete(mountPoint,
+ final boolean transactionState = GbpNetconfTransaction.deleteIfExists(mountPoint,
VppIidFactory.getL2ForInterfaceIid(ifaceKey), GbpNetconfTransaction.RETRY_COUNT);
if (transactionState) {
LOG.debug("Removing bridge domain from interface {}", VppIidFactory.getInterfaceIID(ifaceKey));
InstanceIdentifier<L2> l2Iid =
interfaceIid.builder().augmentation(VppInterfaceAugmentation.class).child(L2.class).build();
LOG.debug("Deleting bridge domain from interface {}", interfacePath);
- final boolean transactionState = GbpNetconfTransaction.delete(mountpoint, l2Iid,
+ final boolean transactionState = GbpNetconfTransaction.deleteIfExists(mountpoint, l2Iid,
GbpNetconfTransaction.RETRY_COUNT);
if (transactionState) {
return vppEndpointLocationProvider.replaceLocationForEndpoint(new ExternalLocationCaseBuilder()
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.ConfigCommand;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
public class GbpNetconfTransaction {
- public static final byte RETRY_COUNT = 5;
+ public static final byte RETRY_COUNT = 3;
private static final Logger LOG = LoggerFactory.getLogger(GbpNetconfTransaction.class);
/**
* @param retryCounter number of attempts
* @return true if transaction is successful, false otherwise
*/
- public synchronized static boolean write(final DataBroker mountpoint, final ConfigCommand command,
+ public static synchronized boolean write(final DataBroker mountpoint, final ConfigCommand command,
byte retryCounter) {
LOG.trace("Netconf WRITE transaction started. RetryCounter: {}", retryCounter);
Preconditions.checkNotNull(mountpoint);
command.execute(rwTx);
final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
futureTask.get();
- LOG.trace("Netconf WRITE transaction done. Retry counter: {}", retryCounter);
+ LOG.trace("Netconf WRITE transaction done for command {}", command);
return true;
- } catch (IllegalStateException e) {
+ } catch (Exception e) {
// Retry
if (retryCounter > 0) {
- LOG.warn("Assuming that netconf write-transaction failed, restarting ...", e.getMessage());
+ LOG.warn("Netconf WRITE transaction failed to {}. Restarting transaction ... ", e.getMessage());
return write(mountpoint, command, --retryCounter);
} else {
- LOG.warn("Netconf write-transaction failed. Maximal number of attempts reached", e.getMessage());
+ LOG.warn("Netconf WRITE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
return false;
}
- } catch (Exception e) {
- LOG.warn("Exception while writing data ...", e.getMessage());
- return false;
}
}
* @param <T> generic data type. Has to be child of {@link DataObject}
* @return true if transaction is successful, false otherwise
*/
- public synchronized static <T extends DataObject> boolean write(final DataBroker mountpoint,
+ public static synchronized <T extends DataObject> boolean write(final DataBroker mountpoint,
final InstanceIdentifier<T> iid,
final T data,
byte retryCounter) {
rwTx.put(LogicalDatastoreType.CONFIGURATION, iid, data, true);
final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
futureTask.get();
- LOG.trace("Netconf WRITE transaction done. Retry counter: {}", retryCounter);
+ LOG.trace("Netconf WRITE transaction done for {}", iid);
return true;
- } catch (IllegalStateException e) {
+ } catch (Exception e) {
// Retry
if (retryCounter > 0) {
- LOG.warn("Assuming that netconf write-transaction failed, restarting ...", e.getMessage());
+ LOG.warn("Netconf WRITE transaction failed to {}. Restarting transaction ... ", e.getMessage());
return write(mountpoint, iid, data, --retryCounter);
} else {
- LOG.warn("Netconf write-transaction failed. Maximal number of attempts reached", e.getMessage());
+ LOG.warn("Netconf WRITE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
return false;
}
- } catch (Exception e) {
- LOG.warn("Exception while writing data ...", e.getMessage());
- return false;
}
}
* @param <T> generic data type. Has to be child of {@link DataObject}
* @return optional data object if successful, {@link Optional#absent()} if failed
*/
- public synchronized static <T extends DataObject> Optional<T> read(final DataBroker mountpoint,
+ public static synchronized <T extends DataObject> Optional<T> read(final DataBroker mountpoint,
final LogicalDatastoreType datastoreType,
final InstanceIdentifier<T> iid,
byte retryCounter) {
final CheckedFuture<Optional<T>, ReadFailedException> futureData =
rTx.read(datastoreType, iid);
data = futureData.get();
- LOG.trace("Netconf READ transaction done. Data present: {}, Retry counter: {}",
- data.isPresent(), retryCounter);
+ LOG.trace("Netconf READ transaction done. Data present: {}", data.isPresent());
return data;
- } catch (IllegalStateException e) {
+ } catch (Exception e) {
// Retry
if (retryCounter > 0) {
- LOG.warn("Assuming that netconf read-transaction failed, restarting ...", e.getMessage());
+ LOG.warn("Netconf READ transaction failed to {}. Restarting transaction ... ", e.getMessage());
rTx.close();
return read(mountpoint, datastoreType, iid, --retryCounter);
} else {
- LOG.warn("Netconf read-transaction failed. Maximal number of attempts reached", e.getMessage());
+ LOG.warn("Netconf READ transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
return Optional.absent();
}
- } catch (Exception e) {
- LOG.warn("Exception while reading data ...", e.getMessage());
- return Optional.absent();
}
}
/**
- * Remove data from remote device using {@link ConfigCommand}. Transaction is restarted if failed.
+ * Remove data from remote device using {@link ConfigCommand}
*
* @param mountpoint to access remote device
* @param command config command with data, datastore type and iid
* @param retryCounter number of attempts
* @return true if transaction is successful, false otherwise
*/
- public synchronized static boolean delete(final DataBroker mountpoint, final ConfigCommand command,
+ public static synchronized boolean deleteIfExists(final DataBroker mountpoint, final ConfigCommand command,
byte retryCounter) {
- LOG.trace("Netconf DELETE transaction started. RetryCounter: {}", retryCounter);
Preconditions.checkNotNull(mountpoint);
- final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
- try {
- command.execute(rwTx);
- final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
- futureTask.get();
- LOG.trace("Netconf DELETE transaction done. Retry counter: {}", retryCounter);
- return true;
- } catch (IllegalStateException e) {
- // Retry
- if (retryCounter > 0) {
- LOG.warn("Assuming that netconf delete-transaction failed, restarting ...", e.getMessage());
- return delete(mountpoint, command, --retryCounter);
- } else {
- LOG.warn("Netconf delete-transaction failed. Maximal number of attempts reached", e.getMessage());
- return false;
- }
- } catch (Exception e) {
- LOG.warn("Exception while removing data ...", e.getMessage());
- return false;
- }
+ InstanceIdentifier<Interface> iid = VppIidFactory.getInterfaceIID(command.getInterfaceBuilder().getKey());
+ return deleteIfExists(mountpoint, iid, retryCounter);
}
/**
- * Remove data from remote device. Transaction is restarted if failed.
+ * Remove data from remote device. Data presence is verified before removal. Transaction is restarted if failed.
*
* @param mountpoint to access remote device
* @param iid data identifier
* @param <T> generic data type. Has to be child of {@link DataObject}
* @return true if transaction is successful, false otherwise
*/
- public synchronized static <T extends DataObject> boolean delete(final DataBroker mountpoint,
+ public static synchronized <T extends DataObject> boolean deleteIfExists(final DataBroker mountpoint,
final InstanceIdentifier<T> iid,
byte retryCounter) {
- LOG.trace("Netconf DELETE transaction started. RetryCounter: {}", retryCounter);
+ LOG.trace("Netconf DELETE transaction started. Data will be read at first. RetryCounter: {}", retryCounter);
Preconditions.checkNotNull(mountpoint);
+ final Optional<T> optionalObject = read(mountpoint, LogicalDatastoreType.CONFIGURATION, iid, RETRY_COUNT);
+ if (!optionalObject.isPresent()) {
+ LOG.warn("Netconf DELETE transaction aborted. Data to remove are not present or cannot be read. Iid: {}",
+ iid);
+ // Return true, this state is not considered as an error
+ return true;
+ }
final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
try {
rwTx.delete(LogicalDatastoreType.CONFIGURATION, iid);
final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
futureTask.get();
- LOG.trace("Netconf DELETE transaction done. Retry counter: {}", retryCounter);
+ LOG.trace("Netconf DELETE transaction done for {}", iid);
return true;
- } catch (IllegalStateException e) {
+ } catch (Exception e) {
// Retry
if (retryCounter > 0) {
- LOG.warn("Assuming that netconf delete-transaction failed, restarting ...", e.getMessage());
- return delete(mountpoint, iid, --retryCounter);
+ LOG.warn("Netconf DELETE transaction failed to {}. Restarting transaction ... ", e.getMessage());
+ return deleteIfExists(mountpoint, iid, --retryCounter);
} else {
- LOG.warn("Netconf delete-transaction failed. Maximal number of attempts reached", e.getMessage());
+ LOG.warn("Netconf DELETE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
return false;
}
- } catch (Exception e) {
- LOG.warn("Exception while removing data ...", e.getMessage());
- return false;
}
}
-
-}
+}
\ No newline at end of file
import com.google.common.base.Optional;
import com.google.common.util.concurrent.CheckedFuture;
+import org.junit.Before;
import org.junit.Test;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.ConfigCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.LoopbackCommand;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
public class GbpNetconfTransactionTest {
+ private final String INTERFACE_KEY = "interface-key";
+ private final String NODE_ID = "node-id";
private final DataBroker dataBroker = mock(DataBroker.class);
private final ReadWriteTransaction rwTx = mock(ReadWriteTransaction.class);
private final ReadOnlyTransaction rTx = mock(ReadOnlyTransaction.class);
private final CheckedFuture<Void, TransactionCommitFailedException> future = mock(CheckedFuture.class);
@SuppressWarnings("unchecked")
private final CheckedFuture<Optional<Node>, ReadFailedException> futureNode = mock(CheckedFuture.class);
- private final ConfigCommand command = mock(ConfigCommand.class);
+ @SuppressWarnings("unchecked")
+ private final CheckedFuture<Optional<Interface>, ReadFailedException> futureInterface = mock(CheckedFuture.class);
+ private final ConfigCommand command = mock(LoopbackCommand.class);
+ private final InterfaceBuilder interfaceBuilder = new InterfaceBuilder().setKey(new InterfaceKey(INTERFACE_KEY));
- @Test
- public void writeConfigCommandExceptionTest() {
+ @Before
+ public void init() {
+ when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
when(dataBroker.newReadWriteTransaction()).thenReturn(rwTx);
- doThrow(new RuntimeException()).when(command).execute(rwTx);
-
- final boolean result = GbpNetconfTransaction.write(dataBroker, command, (byte)5);
- verify(dataBroker, times(1)).newReadWriteTransaction();
- assertFalse(result);
-
}
@Test
public void writeConfigCommandReattemptTest() {
- when(dataBroker.newReadWriteTransaction()).thenReturn(rwTx);
doThrow(new IllegalStateException()).when(command).execute(rwTx);
final boolean result = GbpNetconfTransaction.write(dataBroker, command, (byte)5);
@Test
public void writeConfigCommandTest() throws Exception {
- when(dataBroker.newReadWriteTransaction()).thenReturn(rwTx);
when(rwTx.submit()).thenReturn(future);
doNothing().when(command).execute(rwTx);
when(future.get()).thenReturn(null);
assertTrue(result);
}
- @Test
- public void writeDataExceptionTest() {
- when(dataBroker.newReadWriteTransaction()).thenReturn(rwTx);
- doThrow(new RuntimeException()).when(rwTx).put(LogicalDatastoreType.CONFIGURATION, nodeIid, node, true);
-
- final boolean result = GbpNetconfTransaction.write(dataBroker, nodeIid, node, (byte)5);
- verify(dataBroker, times(1)).newReadWriteTransaction();
- assertFalse(result);
- }
-
@Test
public void writeDataReattemptTest() {
- when(dataBroker.newReadWriteTransaction()).thenReturn(rwTx);
doThrow(new IllegalStateException()).when(rwTx).put(LogicalDatastoreType.CONFIGURATION, nodeIid, node, true);
final boolean result = GbpNetconfTransaction.write(dataBroker, nodeIid, node, (byte)5);
@Test
public void writeDataTest() throws Exception {
- when(dataBroker.newReadWriteTransaction()).thenReturn(rwTx);
when(rwTx.submit()).thenReturn(future);
doNothing().when(rwTx).put(LogicalDatastoreType.CONFIGURATION, nodeIid, node, true);
when(future.get()).thenReturn(null);
assertTrue(result);
}
- @Test
- public void readDataExceptionTest() {
- when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
- doThrow(new RuntimeException()).when(rTx).read(LogicalDatastoreType.CONFIGURATION, nodeIid);
-
- final Optional<Node> result = GbpNetconfTransaction.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
- nodeIid, (byte)5);
- verify(dataBroker, times(1)).newReadOnlyTransaction();
- assertFalse(result.isPresent());
- }
-
@Test
public void readDataReattemptTest() {
- when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
doThrow(new IllegalStateException()).when(rTx).read(LogicalDatastoreType.CONFIGURATION, nodeIid);
final Optional<Node> result = GbpNetconfTransaction.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
@Test
public void readDataTest() throws Exception {
- when(dataBroker.newReadOnlyTransaction()).thenReturn(rTx);
when(rTx.read(LogicalDatastoreType.CONFIGURATION, nodeIid)).thenReturn(futureNode);
when(futureNode.get()).thenReturn(Optional.of(new NodeBuilder()
- .setKey(new NodeKey(new NodeId("node"))).build()));
+ .setKey(new NodeKey(new NodeId(NODE_ID))).build()));
final Optional<Node> result = GbpNetconfTransaction.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
nodeIid, (byte)5);
}
@Test
- public void deleteConfigCommandExceptionTest() {
- when(dataBroker.newReadWriteTransaction()).thenReturn(rwTx);
- doThrow(new RuntimeException()).when(command).execute(rwTx);
+ public void deleteConfigCommandMissingDataTest() throws Exception {
+ final InstanceIdentifier<Interface> iid = VppIidFactory.getInterfaceIID(interfaceBuilder.getKey());
+ when(command.getInterfaceBuilder()).thenReturn(interfaceBuilder);
+ when(rTx.read(LogicalDatastoreType.CONFIGURATION, iid)).thenReturn(futureInterface);
+ when(futureInterface.get()).thenReturn(Optional.absent());
+ doThrow(new IllegalStateException()).when(command).execute(rwTx);
- final boolean result = GbpNetconfTransaction.delete(dataBroker, command, (byte)5);
- verify(dataBroker, times(1)).newReadWriteTransaction();
- assertFalse(result);
+ final boolean result = GbpNetconfTransaction.deleteIfExists(dataBroker, command, (byte)5);
+ verify(dataBroker, times(1)).newReadOnlyTransaction();
+ assertTrue(result);
}
@Test
- public void deleteConfigCommandReattemptTest() {
- when(dataBroker.newReadWriteTransaction()).thenReturn(rwTx);
+ public void deleteConfigCommandReattemptTest() throws Exception {
+ final InstanceIdentifier<Interface> iid = VppIidFactory.getInterfaceIID(interfaceBuilder.getKey());
+ when(command.getInterfaceBuilder()).thenReturn(interfaceBuilder);
+ when(rTx.read(LogicalDatastoreType.CONFIGURATION, iid)).thenReturn(futureInterface);
+ when(futureInterface.get()).thenReturn(Optional.of(new InterfaceBuilder()
+ .setKey(new InterfaceKey(INTERFACE_KEY)).build()));
doThrow(new IllegalStateException()).when(command).execute(rwTx);
- final boolean result = GbpNetconfTransaction.delete(dataBroker, command, (byte)5);
+ final boolean result = GbpNetconfTransaction.deleteIfExists(dataBroker, command, (byte)5);
verify(dataBroker, times(6)).newReadWriteTransaction();
assertFalse(result);
}
@Test
public void deleteConfigCommandTest() throws Exception {
- when(dataBroker.newReadWriteTransaction()).thenReturn(rwTx);
+ final InstanceIdentifier<Interface> iid = VppIidFactory.getInterfaceIID(interfaceBuilder.getKey());
+ when(command.getInterfaceBuilder()).thenReturn(interfaceBuilder);
+ when(rTx.read(LogicalDatastoreType.CONFIGURATION, iid)).thenReturn(futureInterface);
+ when(futureInterface.get()).thenReturn(Optional.of(new InterfaceBuilder()
+ .setKey(new InterfaceKey(INTERFACE_KEY)).build()));
when(rwTx.submit()).thenReturn(future);
doNothing().when(command).execute(rwTx);
when(future.get()).thenReturn(null);
- final boolean result = GbpNetconfTransaction.delete(dataBroker, command, (byte)5);
+ final boolean result = GbpNetconfTransaction.deleteIfExists(dataBroker, command, (byte)5);
verify(dataBroker, times(1)).newReadWriteTransaction();
assertTrue(result);
}
@Test
- public void deleteDataExceptionTest() {
- when(dataBroker.newReadWriteTransaction()).thenReturn(rwTx);
- doThrow(new RuntimeException()).when(rwTx).delete(LogicalDatastoreType.CONFIGURATION, nodeIid);
+ public void deleteDataMissingDataTest() throws Exception {
+ when(rTx.read(LogicalDatastoreType.CONFIGURATION, nodeIid)).thenReturn(futureNode);
+ when(futureNode.get()).thenReturn(Optional.absent());
+ doThrow(new IllegalStateException()).when(command).execute(rwTx);
- final boolean result = GbpNetconfTransaction.delete(dataBroker, nodeIid, (byte)5);
- verify(dataBroker, times(1)).newReadWriteTransaction();
- assertFalse(result);
+ final boolean result = GbpNetconfTransaction.deleteIfExists(dataBroker, nodeIid, (byte)5);
+ verify(dataBroker, times(1)).newReadOnlyTransaction();
+ assertTrue(result);
}
@Test
- public void deleteDataReattemptTest() {
- when(dataBroker.newReadWriteTransaction()).thenReturn(rwTx);
+ public void deleteDataReattemptTest() throws Exception {
+ when(rTx.read(LogicalDatastoreType.CONFIGURATION, nodeIid)).thenReturn(futureNode);
+ when(futureNode.get()).thenReturn(Optional.of(new NodeBuilder()
+ .setKey(new NodeKey(new NodeId(NODE_ID))).build()));
doThrow(new IllegalStateException()).when(rwTx).delete(LogicalDatastoreType.CONFIGURATION, nodeIid);
- final boolean result = GbpNetconfTransaction.delete(dataBroker, nodeIid, (byte)5);
+ final boolean result = GbpNetconfTransaction.deleteIfExists(dataBroker, nodeIid, (byte)5);
verify(dataBroker, times(6)).newReadWriteTransaction();
assertFalse(result);
}
@Test
public void deleteDataTest() throws Exception {
- when(dataBroker.newReadWriteTransaction()).thenReturn(rwTx);
+ when(rTx.read(LogicalDatastoreType.CONFIGURATION, nodeIid)).thenReturn(futureNode);
+ when(futureNode.get()).thenReturn(Optional.of(new NodeBuilder()
+ .setKey(new NodeKey(new NodeId(NODE_ID))).build()));
when(rwTx.submit()).thenReturn(future);
doNothing().when(rwTx).delete(LogicalDatastoreType.CONFIGURATION, nodeIid);
when(future.get()).thenReturn(null);
- final boolean result = GbpNetconfTransaction.delete(dataBroker, nodeIid, (byte)5);
+ final boolean result = GbpNetconfTransaction.deleteIfExists(dataBroker, nodeIid, (byte)5);
verify(dataBroker, times(1)).newReadWriteTransaction();
assertTrue(result);
}