Bug 3765: Restore dao from mdsal config datastore at startup 15/22815/1
authorFlorin Coras <fcoras@cisco.com>
Wed, 17 Jun 2015 02:30:18 +0000 (19:30 -0700)
committerFlorin Coras <fcoras@cisco.com>
Wed, 17 Jun 2015 18:39:16 +0000 (11:39 -0700)
Change-Id: Iedbe7973aec8955f4573eca2c3d26bee69075b19
Signed-off-by: Florin Coras <fcoras@cisco.com>
mappingservice/implementation/src/main/java/org/opendaylight/lispflowmapping/implementation/LispMappingService.java
mappingservice/implementation/src/main/java/org/opendaylight/lispflowmapping/implementation/mdsal/DataStoreBackEnd.java

index 2efb485002185a55818356138adba414d82f9e35..32eb945d17d413a7dfed1d43b465a1a7455ed6b9 100644 (file)
@@ -32,6 +32,7 @@ import org.opendaylight.lispflowmapping.implementation.serializer.LispMessage;
 import org.opendaylight.lispflowmapping.implementation.util.LispAFIConvertor;
 import org.opendaylight.lispflowmapping.implementation.util.LispAddressStringifier;
 import org.opendaylight.lispflowmapping.implementation.util.LispNotificationHelper;
+import org.opendaylight.lispflowmapping.implementation.util.MapServerMapResolverUtil;
 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
 import org.opendaylight.lispflowmapping.interfaces.dao.ILispTypeConverter;
 import org.opendaylight.lispflowmapping.interfaces.dao.IRowVisitor;
@@ -59,6 +60,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.transportaddress.TransportAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.control.plane.rev150314.transportaddress.TransportAddressBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mapping.database.rev150314.LfmMappingDatabaseService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mapping.database.rev150314.MappingOrigin;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mapping.database.rev150314.db.instance.AuthenticationKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mapping.database.rev150314.db.instance.Mapping;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
@@ -117,7 +120,7 @@ public class LispMappingService implements IFlowMapping, IFlowMappingShell, Bind
 
         LfmMappingDatabaseRpc mappingDbProviderRpc = new LfmMappingDatabaseRpc(dataBrokerService);
         lfmDbRpc = rpcRegistry.addRpcImplementation(LfmMappingDatabaseService.class, mappingDbProviderRpc);
-
+        dsbe = new DataStoreBackEnd(dataBrokerService);
         setLispDao(new HashMapDb());
     }
 
@@ -157,6 +160,7 @@ public class LispMappingService implements IFlowMapping, IFlowMappingShell, Bind
     void setLispDao(ILispDAO dao) {
         LOG.trace("LispDAO set in LispMappingService");
         basicInit(dao);
+        restoreDaoFromDatastore();
     }
 
     void unsetLispDao(ILispDAO dao) {
@@ -166,6 +170,33 @@ public class LispMappingService implements IFlowMapping, IFlowMappingShell, Bind
         lispDao = null;
     }
 
+    private void restoreDaoFromDatastore() {
+        List<Mapping> mappings = dsbe.getAllMappings();
+        List<AuthenticationKey> authKeys = dsbe.getAllAuthenticationKeys();
+
+        LOG.info("Restoring {} mappings and {} keys from datastore into DAO", mappings.size(), authKeys.size());
+
+        // restore southbound registered entries first ...
+        for (Mapping mapping : mappings) {
+            if (mapping.getOrigin() == MappingOrigin.Southbound) {
+                MapRegister register = MapServerMapResolverUtil.getMapRegister(mapping);
+                handleMapRegister(register, false);
+            }
+        }
+
+        // because northbound registrations have priority
+        for (Mapping mapping : mappings) {
+            if (mapping.getOrigin() == MappingOrigin.Northbound) {
+                MapRegister register = MapServerMapResolverUtil.getMapRegister(mapping);
+                handleMapRegister(register, false);
+            }
+        }
+
+        for (AuthenticationKey authKey : authKeys) {
+            addAuthenticationKey(authKey.getLispAddressContainer(), authKey.getMaskLength(), authKey.getAuthkey());
+        }
+    }
+
     public void destroy() {
         LOG.info("LISP (RFC6830) Mapping Service is destroyed!");
         mapResolver = null;
index ecda8addad47016a65429c773eb188c02166d683..ce36c5ddb2cdf65b6f67243cfc97607ffff4c42f 100644 (file)
@@ -7,20 +7,26 @@
  */
 package org.opendaylight.lispflowmapping.implementation.mdsal;
 
-import java.util.concurrent.ExecutionException;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 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.lispflowmapping.implementation.util.InstanceIdentifierUtil;
 import org.opendaylight.lispflowmapping.implementation.util.LispAddressStringifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mapping.database.rev150314.MappingDatabase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mapping.database.rev150314.db.instance.AuthenticationKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mapping.database.rev150314.db.instance.Mapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mapping.database.rev150314.mapping.database.InstanceId;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
 
 /**
@@ -46,10 +52,8 @@ public class DataStoreBackEnd {
         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
                 .createAuthenticationKeyIid(authenticationKey.getLispAddressContainer(),
                         authenticationKey.getMaskLength());
-        WriteTransaction transaction = broker.newWriteOnlyTransaction();
-        transaction.put(LogicalDatastoreType.CONFIGURATION, path, authenticationKey, true);
-        CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
-        checkTransaction(future, "Adding authentication key to config datastrore failed");
+        writePutTransaction(path, authenticationKey, LogicalDatastoreType.CONFIGURATION,
+                "Adding authentication key to config datastrore failed");
     }
 
     public void addMapping(Mapping mapping) {
@@ -58,10 +62,8 @@ public class DataStoreBackEnd {
 
         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
                 .createMappingIid(mapping.getLispAddressContainer(), mapping.getMaskLength(), mapping.getOrigin());
-        WriteTransaction transaction = broker.newWriteOnlyTransaction();
-        transaction.put(LogicalDatastoreType.CONFIGURATION, path, mapping, true);
-        CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
-        checkTransaction(future, "Adding mapping to config datastrore failed");
+        writePutTransaction(path, mapping, LogicalDatastoreType.CONFIGURATION,
+                "Adding mapping to config datastrore failed");
     }
 
     public void removeAuthenticationKey(AuthenticationKey authenticationKey) {
@@ -72,10 +74,8 @@ public class DataStoreBackEnd {
         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
                 .createAuthenticationKeyIid(authenticationKey.getLispAddressContainer(),
                         authenticationKey.getMaskLength());
-        WriteTransaction transaction = broker.newWriteOnlyTransaction();
-        transaction.delete(LogicalDatastoreType.CONFIGURATION, path);
-        CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
-        checkTransaction(future, "Deleting authentication key from config datastrore failed");
+        deleteTransaction(path, LogicalDatastoreType.CONFIGURATION,
+                "Deleting authentication key from config datastrore failed");
     }
 
     public void removeMapping(Mapping mapping) {
@@ -84,10 +84,7 @@ public class DataStoreBackEnd {
 
         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
                 .createMappingIid(mapping.getLispAddressContainer(), mapping.getMaskLength(), mapping.getOrigin());
-        WriteTransaction transaction = broker.newWriteOnlyTransaction();
-        transaction.delete(LogicalDatastoreType.CONFIGURATION, path);
-        CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
-        checkTransaction(future, "Deleting mapping from config datastrore failed");
+        deleteTransaction(path, LogicalDatastoreType.CONFIGURATION, "Deleting mapping from config datastrore failed");
     }
 
     public void updateAuthenticationKey(AuthenticationKey authenticationKey) {
@@ -98,10 +95,8 @@ public class DataStoreBackEnd {
         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
                 .createAuthenticationKeyIid(authenticationKey.getLispAddressContainer(),
                         authenticationKey.getMaskLength());
-        WriteTransaction transaction = broker.newWriteOnlyTransaction();
-        transaction.put(LogicalDatastoreType.CONFIGURATION, path, authenticationKey, true);
-        CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
-        checkTransaction(future, "Updating authentication key in config datastrore failed");
+        writePutTransaction(path, authenticationKey, LogicalDatastoreType.CONFIGURATION,
+                "Updating authentication key in config datastrore failed");
     }
 
     public void updateMapping(Mapping mapping) {
@@ -110,17 +105,89 @@ public class DataStoreBackEnd {
 
         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
                 .createMappingIid(mapping.getLispAddressContainer(), mapping.getMaskLength(), mapping.getOrigin());
-        WriteTransaction transaction = broker.newWriteOnlyTransaction();
-        transaction.put(LogicalDatastoreType.CONFIGURATION, path, mapping, true);
-        CheckedFuture<Void, TransactionCommitFailedException> future = transaction.submit();
-        checkTransaction(future, "Updating mapping in config datastrore failed");
+        writePutTransaction(path, mapping, LogicalDatastoreType.CONFIGURATION,
+                "Updating mapping in config datastrore failed");
     }
 
-    void checkTransaction(CheckedFuture<Void, TransactionCommitFailedException> future, String errMsg) {
+    public List<Mapping> getAllMappings() {
+        LOG.debug("MD-SAL: Get all mappings from datastore");
+        List<Mapping> mappings = new ArrayList<Mapping>();
+        InstanceIdentifier<MappingDatabase> path = InstanceIdentifier.create(MappingDatabase.class);
+        MappingDatabase mdb = readTransaction(path, LogicalDatastoreType.CONFIGURATION);
+
+        if (mdb != null) {
+            for (InstanceId id : mdb.getInstanceId()) {
+                mappings.addAll(id.getMapping());
+            }
+        }
+
+        return mappings;
+    }
+
+    public List<AuthenticationKey> getAllAuthenticationKeys() {
+        LOG.debug("MD-SAL: Get all authentication keys from datastore");
+        List<AuthenticationKey> keys = new ArrayList<AuthenticationKey>();
+        InstanceIdentifier<MappingDatabase> path = InstanceIdentifier.create(MappingDatabase.class);
+        MappingDatabase mdb = readTransaction(path, LogicalDatastoreType.CONFIGURATION);
+
+        if (mdb != null) {
+            for (InstanceId id : mdb.getInstanceId()) {
+                keys.addAll(id.getAuthenticationKey());
+            }
+        }
+
+        return keys;
+    }
+
+    private <U extends org.opendaylight.yangtools.yang.binding.DataObject> boolean writePutTransaction(
+            InstanceIdentifier<U> addIID, U data, LogicalDatastoreType logicalDatastoreType, String errMsg) {
+        boolean ret;
+        WriteTransaction writeTx = broker.newWriteOnlyTransaction();
+        writeTx.put(logicalDatastoreType, addIID, data, true);
+        CheckedFuture<Void, TransactionCommitFailedException> submitFuture = writeTx.submit();
+        try {
+            submitFuture.checkedGet();
+            ret = true;
+        } catch (TransactionCommitFailedException e) {
+            LOG.error("{} : {}", errMsg, e.getMessage());
+            ret = false;
+        }
+        return ret;
+    }
+
+    private <U extends org.opendaylight.yangtools.yang.binding.DataObject> U readTransaction(
+            InstanceIdentifier<U> readIID, LogicalDatastoreType logicalDatastoreType) {
+        U ret = null;
+        ReadOnlyTransaction readTx = broker.newReadOnlyTransaction();
+        Optional<U> optionalDataObject;
+        CheckedFuture<Optional<U>, ReadFailedException> submitFuture = readTx.read(logicalDatastoreType, readIID);
+        try {
+            optionalDataObject = submitFuture.checkedGet();
+            if (optionalDataObject != null && optionalDataObject.isPresent()) {
+                ret = optionalDataObject.get();
+            } else {
+                LOG.debug("{}: Failed to read", Thread.currentThread().getStackTrace()[1]);
+            }
+        } catch (ReadFailedException e) {
+            LOG.warn("Failed to ....", e);
+        }
+        return ret;
+    }
+
+    private <U extends org.opendaylight.yangtools.yang.binding.DataObject> boolean deleteTransaction(
+            InstanceIdentifier<U> deleteIID, LogicalDatastoreType logicalDatastoreType, String errMsg) {
+        boolean ret = false;
+
+        WriteTransaction writeTx = broker.newWriteOnlyTransaction();
+        writeTx.delete(logicalDatastoreType, deleteIID);
+        CheckedFuture<Void, TransactionCommitFailedException> submitFuture = writeTx.submit();
         try {
-            future.get();
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.warn(errMsg + e);
+            submitFuture.checkedGet();
+            ret = true;
+        } catch (TransactionCommitFailedException e) {
+            LOG.error("{} : {}", errMsg, e.getMessage());
+            ret = false;
         }
+        return ret;
     }
 }