Move southbound mappings to OPERATIONAL
[lispflowmapping.git] / mappingservice / implementation / src / main / java / org / opendaylight / lispflowmapping / implementation / mdsal / DataStoreBackEnd.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.lispflowmapping.implementation.mdsal;
9
10 import java.util.ArrayList;
11 import java.util.List;
12
13 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
16 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
17 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
20 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
21 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
22 import org.opendaylight.lispflowmapping.implementation.util.InstanceIdentifierUtil;
23 import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingDatabase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.AuthenticationKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.Mapping;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.database.VirtualNetworkIdentifier;
29 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 import com.google.common.base.Optional;
34 import com.google.common.util.concurrent.CheckedFuture;
35 import com.google.common.util.concurrent.FutureCallback;
36 import com.google.common.util.concurrent.Futures;
37
38 /**
39  * Stores data coming from the mapping database RPCs into the config datastore.
40  *
41  * @author Lorand Jakab
42  *
43  */
44 public class DataStoreBackEnd implements TransactionChainListener {
45     protected static final Logger LOG = LoggerFactory.getLogger(DataStoreBackEnd.class);
46     private static final InstanceIdentifier<MappingDatabase> DATABASE_ROOT =
47             InstanceIdentifier.create(MappingDatabase.class);
48     private BindingTransactionChain txChain;
49
50     public DataStoreBackEnd(DataBroker broker) {
51         this.txChain = broker.createTransactionChain(this);
52     }
53
54     public void addAuthenticationKey(AuthenticationKey authenticationKey) {
55         LOG.debug("MD-SAL: Adding authentication key '{}' for {}", authenticationKey.getMappingAuthkey().getKeyString(),
56                 LispAddressStringifier.getString(authenticationKey.getEid()));
57
58         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
59                 .createAuthenticationKeyIid(authenticationKey.getEid());
60         writePutTransaction(path, authenticationKey, LogicalDatastoreType.CONFIGURATION,
61                 "Adding authentication key to config datastrore failed");
62     }
63
64     public void addMapping(Mapping mapping) {
65         LOG.debug("MD-SAL: Adding mapping for {}",
66                 LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
67
68         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
69                 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
70         writePutTransaction(path, mapping, getDestinationDatastore(mapping),
71                 "Adding mapping to config datastrore failed");
72     }
73
74     public void removeAuthenticationKey(AuthenticationKey authenticationKey) {
75         LOG.debug("MD-SAL: Removing authentication key for {}",
76                 LispAddressStringifier.getString(authenticationKey.getEid()));
77
78         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
79                 .createAuthenticationKeyIid(authenticationKey.getEid());
80         deleteTransaction(path, LogicalDatastoreType.CONFIGURATION,
81                 "Deleting authentication key from config datastrore failed");
82     }
83
84     public void removeMapping(Mapping mapping) {
85         LOG.debug("MD-SAL: Removing mapping for {}",
86                 LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
87
88         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
89                 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
90         deleteTransaction(path, getDestinationDatastore(mapping), "Deleting mapping from config datastrore failed");
91     }
92
93     public void removeAllMappings() {
94         LOG.debug("MD-SAL: Removing all mappings");
95         removeAllConfigurationMappings();
96         removeAllOperationalMappings();
97     }
98
99     public void removeAllConfigurationMappings() {
100         deleteTransaction(DATABASE_ROOT, LogicalDatastoreType.CONFIGURATION,
101                 "Removing of all mappings in config datastore failed");
102     }
103
104     public void removeAllOperationalMappings() {
105         deleteTransaction(DATABASE_ROOT, LogicalDatastoreType.OPERATIONAL,
106                 "Removing of all mappings in operational datastore failed");
107     }
108
109     public void updateAuthenticationKey(AuthenticationKey authenticationKey) {
110         LOG.debug("MD-SAL: Updating authentication key for {} with '{}'",
111                 LispAddressStringifier.getString(authenticationKey.getEid()),
112                 authenticationKey.getMappingAuthkey().getKeyString());
113
114         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
115                 .createAuthenticationKeyIid(authenticationKey.getEid());
116         writePutTransaction(path, authenticationKey, LogicalDatastoreType.CONFIGURATION,
117                 "Updating authentication key in config datastrore failed");
118     }
119
120     public void updateMapping(Mapping mapping) {
121         LOG.debug("MD-SAL: Updating mapping for {}",
122                 LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
123
124         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
125                 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
126         writePutTransaction(path, mapping, LogicalDatastoreType.CONFIGURATION,
127                 "Updating mapping in config datastrore failed");
128     }
129
130     public List<Mapping> getAllMappings() {
131         List<Mapping> mappings = getAllMappings(LogicalDatastoreType.CONFIGURATION);
132         mappings.addAll(getAllMappings(LogicalDatastoreType.OPERATIONAL));
133         return mappings;
134     }
135
136     public List<Mapping> getAllMappings(LogicalDatastoreType logicalDataStore) {
137         LOG.debug("MD-SAL: Get all mappings from datastore");
138         List<Mapping> mappings = new ArrayList<Mapping>();
139         MappingDatabase mdb = readTransaction(DATABASE_ROOT, logicalDataStore);
140
141         if (mdb != null) {
142             for (VirtualNetworkIdentifier id : mdb.getVirtualNetworkIdentifier()) {
143                 List<Mapping> ms = id.getMapping();
144                 if (ms != null) {
145                     mappings.addAll(ms);
146                 }
147             }
148         }
149
150         return mappings;
151     }
152
153     public List<AuthenticationKey> getAllAuthenticationKeys() {
154         LOG.debug("MD-SAL: Get all authentication keys from datastore");
155         List<AuthenticationKey> authKeys = new ArrayList<AuthenticationKey>();
156         MappingDatabase mdb = readTransaction(DATABASE_ROOT, LogicalDatastoreType.CONFIGURATION);
157
158         if (mdb != null) {
159             for (VirtualNetworkIdentifier id : mdb.getVirtualNetworkIdentifier()) {
160                 List<AuthenticationKey> keys = id.getAuthenticationKey();
161                 if (keys != null) {
162                     authKeys.addAll(keys);
163                 }
164             }
165         }
166
167         return authKeys;
168     }
169
170     private static LogicalDatastoreType getDestinationDatastore(Mapping mapping) {
171         return mapping.getOrigin().equals(MappingOrigin.Southbound) ? LogicalDatastoreType.OPERATIONAL
172                 : LogicalDatastoreType.CONFIGURATION;
173     }
174
175     private <U extends org.opendaylight.yangtools.yang.binding.DataObject> void writePutTransaction(
176             InstanceIdentifier<U> addIID, U data, LogicalDatastoreType logicalDatastoreType, String errMsg) {
177         WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
178         writeTx.put(logicalDatastoreType, addIID, data, true);
179         Futures.addCallback(writeTx.submit(), new FutureCallback<Void>() {
180             @Override
181             public void onSuccess(Void result) {
182             }
183             @Override
184             public void onFailure(Throwable t) {
185                 LOG.error("Transaction failed:", t);
186             }
187         });
188     }
189
190     private <U extends org.opendaylight.yangtools.yang.binding.DataObject> U readTransaction(
191             InstanceIdentifier<U> readIID, LogicalDatastoreType logicalDatastoreType) {
192         ReadOnlyTransaction readTx = txChain.newReadOnlyTransaction();
193         CheckedFuture<Optional<U>, ReadFailedException> readFuture = readTx.read(logicalDatastoreType, readIID);
194         readTx.close();
195         try {
196             Optional<U> optionalDataObject = readFuture.checkedGet();
197             if (optionalDataObject != null && optionalDataObject.isPresent()) {
198                 return optionalDataObject.get();
199             } else {
200                 LOG.debug("{}: Failed to read", Thread.currentThread().getStackTrace()[1]);
201             }
202         } catch (ReadFailedException e) {
203             LOG.warn("Failed to ....", e);
204         }
205         return null;
206     }
207
208     private <U extends org.opendaylight.yangtools.yang.binding.DataObject> void deleteTransaction(
209             InstanceIdentifier<U> deleteIID, LogicalDatastoreType logicalDatastoreType, String errMsg) {
210
211         WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
212         writeTx.delete(logicalDatastoreType, deleteIID);
213         Futures.addCallback(writeTx.submit(), new FutureCallback<Void>() {
214             @Override
215             public void onSuccess(Void result) {
216             }
217             @Override
218             public void onFailure(Throwable t) {
219                 LOG.error("Transaction failed:", t);
220             }
221         });
222     }
223
224     @Override
225     public void onTransactionChainFailed(TransactionChain<?, ?> chain, AsyncTransaction<?, ?> transaction,
226             Throwable cause) {
227         LOG.error("Broken chain {} in DataStoreBackEnd, transaction {}, cause {}", chain, transaction.getIdentifier(),
228                 cause);
229     }
230
231     @Override
232     public void onTransactionChainSuccessful(TransactionChain<?, ?> chain) {
233         LOG.info("DataStoreBackEnd closed successfully, chain {}", chain);
234     }
235 }