implementing routing for VPP
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / util / GbpNetconfTransaction.java
index 12f5b6acf3d7322e1563e4ad03015dbd53a13617..9c5d01a9004841d366f6dbf95b0df0498e7c9e62 100644 (file)
@@ -17,8 +17,11 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 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.RoutingCommand;
 import org.opendaylight.vbd.impl.transaction.VbdNetconfTransaction;
 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.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocolKey;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -26,6 +29,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
 import com.google.common.util.concurrent.CheckedFuture;
 
 public class GbpNetconfTransaction {
@@ -65,6 +69,21 @@ public class GbpNetconfTransaction {
         return result;
     }
 
+    /***
+     * Netconf wrapper method for synced requests for write operation on a Netconf Device
+     * @param mountpoint    netconf device
+     * @param command       routing command that needs to be executed
+     * @param retryCounter  retry counter, will repeat the operation for specified amount of times if transaction fails
+     * @return true if transaction is successful, false otherwise
+     */
+    public static boolean netconfSyncedWrite(@Nonnull final DataBroker mountpoint, @Nonnull final RoutingCommand command,
+        byte retryCounter) {
+        VbdNetconfTransaction.REENTRANT_LOCK.lock();
+        boolean result = write(mountpoint, command, retryCounter);
+        VbdNetconfTransaction.REENTRANT_LOCK.unlock();
+        return result;
+    }
+
     /***
      * Netconf wrapper method for synced requests for delete operation on a Netconf Device
      * @param mountpoint    netconf device
@@ -96,6 +115,20 @@ public class GbpNetconfTransaction {
         return result;
     }
 
+    /***
+     * Netconf wrapper method for synced requests for delete operation on a Netconf Device
+     * @param mountpoint    netconf device
+     * @param command       routing command that needs to be executed
+     * @param retryCounter  retry counter, will repeat the operation for specified amount of times if transaction fails
+     * @return true if transaction is successful, false otherwise
+     */
+    public static boolean netconfSyncedDelete(@Nonnull final DataBroker mountpoint,
+        @Nonnull final RoutingCommand command, byte retryCounter) {
+        VbdNetconfTransaction.REENTRANT_LOCK.lock();
+        boolean result = deleteIfExists(mountpoint, command, retryCounter);
+        VbdNetconfTransaction.REENTRANT_LOCK.unlock();
+        return result;
+    }
 
     /**
      * Use {@link ConfigCommand} to put data into netconf transaction and submit. Transaction is restarted if failed
@@ -127,6 +160,36 @@ public class GbpNetconfTransaction {
         }
     }
 
+    /**
+     * Use {@link RoutingCommand} to put data into netconf transaction and submit. Transaction is restarted if failed
+     *
+     * @param mountpoint   to access remote device
+     * @param command      routing command with data, datastore type and iid
+     * @param retryCounter number of attempts
+     * @return true if transaction is successful, false otherwise
+     */
+    private static boolean write(final DataBroker mountpoint, final RoutingCommand command, byte retryCounter) {
+        LOG.trace("Netconf WRITE 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 WRITE transaction done for command {}", command);
+            return true;
+        } catch (Exception e) {
+            // Retry
+            if (retryCounter > 0) {
+                LOG.warn("Netconf WRITE transaction failed to {}. Restarting transaction ... ", e.getMessage());
+                return write(mountpoint, command, --retryCounter);
+            } else {
+                LOG.warn("Netconf WRITE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
+                return false;
+            }
+        }
+    }
+
     /**
      * Write data to remote device. Transaction is restarted if failed
      *
@@ -137,10 +200,8 @@ public class GbpNetconfTransaction {
      * @param <T>          generic data type. Has to be child of {@link DataObject}
      * @return true if transaction is successful, false otherwise
      */
-    private static <T extends DataObject> boolean write(final DataBroker mountpoint,
-                                                                    final InstanceIdentifier<T> iid,
-                                                                    final T data,
-                                                                    byte retryCounter) {
+    private static <T extends DataObject> boolean write(final DataBroker mountpoint, final InstanceIdentifier<T> iid,
+        final T data, byte retryCounter) {
         LOG.trace("Netconf WRITE transaction started. RetryCounter: {}", retryCounter);
         Preconditions.checkNotNull(mountpoint);
         final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
@@ -173,16 +234,14 @@ public class GbpNetconfTransaction {
      * @return optional data object if successful, {@link Optional#absent()} if failed
      */
     public static synchronized <T extends DataObject> Optional<T> read(final DataBroker mountpoint,
-                                                                       final LogicalDatastoreType datastoreType,
-                                                                       final InstanceIdentifier<T> iid,
-                                                                       byte retryCounter) {
+        final LogicalDatastoreType datastoreType, final InstanceIdentifier<T> iid, byte retryCounter) {
         LOG.trace("Netconf READ transaction started. RetryCounter: {}", retryCounter);
         Preconditions.checkNotNull(mountpoint);
         final ReadOnlyTransaction rTx = mountpoint.newReadOnlyTransaction();
         Optional<T> data;
         try {
             final CheckedFuture<Optional<T>, ReadFailedException> futureData =
-                    rTx.read(datastoreType, iid);
+                rTx.read(datastoreType, iid);
             data = futureData.get();
             LOG.trace("Netconf READ transaction done. Data present: {}", data.isPresent());
             return data;
@@ -207,13 +266,32 @@ public class GbpNetconfTransaction {
      * @param retryCounter number of attempts
      * @return true if transaction is successful, false otherwise
      */
-    private static boolean deleteIfExists(final DataBroker mountpoint, final ConfigCommand command,
-                                              byte retryCounter) {
+    private static boolean deleteIfExists(final DataBroker mountpoint, final ConfigCommand command, byte retryCounter) {
         Preconditions.checkNotNull(mountpoint);
         InstanceIdentifier<Interface> iid = VppIidFactory.getInterfaceIID(command.getInterfaceBuilder().getKey());
         return deleteIfExists(mountpoint, iid, retryCounter);
     }
 
+    /**
+     * 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
+     */
+    private static boolean deleteIfExists(final DataBroker mountpoint, final RoutingCommand command,
+        byte retryCounter) {
+        Preconditions.checkNotNull(mountpoint);
+        String routerProtocol = command.getRouterProtocol();
+        if (Strings.isNullOrEmpty(routerProtocol)) {
+            routerProtocol = "learned-protocol-0";
+        }
+        InstanceIdentifier<RoutingProtocol> iid =
+            VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(routerProtocol));
+        return deleteIfExists(mountpoint, iid, retryCounter);
+    }
+
     /**
      * Remove data from remote device. Data presence is verified before removal. Transaction is restarted if failed.
      *
@@ -224,14 +302,13 @@ public class GbpNetconfTransaction {
      * @return true if transaction is successful, false otherwise
      */
     private static <T extends DataObject> boolean deleteIfExists(final DataBroker mountpoint,
-                                                                     final InstanceIdentifier<T> iid,
-                                                                     byte retryCounter) {
+        final InstanceIdentifier<T> iid, byte 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);
+                iid);
             // Return true, this state is not considered as an error
             return true;
         }