2 * Copyright (c) 2015 Cisco Systems, Inc. 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
8 package org.opendaylight.lispflowmapping.dsbackend;
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.MoreExecutors;
16 import java.util.ArrayList;
17 import java.util.Date;
18 import java.util.List;
19 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
22 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
26 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
27 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
28 import org.opendaylight.lispflowmapping.lisp.util.LispAddressStringifier;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingDatabase;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.AuthenticationKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.Mapping;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.db.instance.mapping.XtrIdMapping;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.database.LastUpdated;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.database.LastUpdatedBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.database.VirtualNetworkIdentifier;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
43 * Stores data coming from the mapping database RPCs into the MD-SAL datastore.
45 * @author Lorand Jakab
48 public class DataStoreBackEnd implements TransactionChainListener {
49 protected static final Logger LOG = LoggerFactory.getLogger(DataStoreBackEnd.class);
50 private static final InstanceIdentifier<MappingDatabase> DATABASE_ROOT =
51 InstanceIdentifier.create(MappingDatabase.class);
52 private static final InstanceIdentifier<LastUpdated> LAST_UPDATED =
53 InstanceIdentifier.create(MappingDatabase.class).child(LastUpdated.class);
54 private DataBroker broker;
55 private BindingTransactionChain txChain;
57 public DataStoreBackEnd(DataBroker broker) {
59 createTransactionChain();
62 public void createTransactionChain() {
63 LOG.debug("Creating DataStoreBackEnd transaction chain...");
64 txChain = broker.createTransactionChain(this);
67 public void addAuthenticationKey(AuthenticationKey authenticationKey) {
68 if (LOG.isDebugEnabled()) {
69 LOG.debug("MD-SAL: Adding authentication key '{}' for {}",
70 authenticationKey.getMappingAuthkey().getKeyString(),
71 LispAddressStringifier.getString(authenticationKey.getEid()));
74 InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
75 .createAuthenticationKeyIid(authenticationKey.getEid());
76 writePutTransaction(path, authenticationKey, LogicalDatastoreType.CONFIGURATION,
77 "Adding authentication key to MD-SAL datastore failed");
80 public void addMapping(Mapping mapping) {
81 if (LOG.isDebugEnabled()) {
82 LOG.debug("MD-SAL: Adding mapping for {}",
83 LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
86 InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
87 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
88 writePutTransaction(path, mapping, getDestinationDatastore(mapping),
89 "Adding mapping to MD-SAL datastore failed");
92 // This method assumes that it is only called for southbound originated Map-Registers
93 public void addXtrIdMapping(XtrIdMapping mapping) {
94 XtrId xtrId = mapping.getMappingRecord().getXtrId();
95 Preconditions.checkNotNull(xtrId, "Make sure you only call addXtrIdMapping when the MappingRecord "
96 + "contains an xTR-ID");
97 if (LOG.isDebugEnabled()) {
98 LOG.debug("MD-SAL: Adding mapping for {}, xTR-ID {}",
99 LispAddressStringifier.getString(mapping.getMappingRecord().getEid()), xtrId);
102 InstanceIdentifier<XtrIdMapping> path = InstanceIdentifierUtil
103 .createXtrIdMappingIid(mapping.getMappingRecord().getEid(), MappingOrigin.Southbound, xtrId);
104 writePutTransaction(path, mapping, LogicalDatastoreType.OPERATIONAL,
105 "Adding xTR-ID mapping to MD-SAL datastore failed");
108 public void removeAuthenticationKey(AuthenticationKey authenticationKey) {
109 if (LOG.isDebugEnabled()) {
110 LOG.debug("MD-SAL: Removing authentication key for {}",
111 LispAddressStringifier.getString(authenticationKey.getEid()));
114 InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
115 .createAuthenticationKeyIid(authenticationKey.getEid());
116 deleteTransaction(path, LogicalDatastoreType.CONFIGURATION,
117 "Deleting authentication key from MD-SAL datastore failed");
120 public void removeMapping(Mapping mapping) {
121 if (LOG.isDebugEnabled()) {
122 LOG.debug("MD-SAL: Removing mapping for {}",
123 LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
126 InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
127 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
128 deleteTransaction(path, getDestinationDatastore(mapping), "Deleting mapping from MD-SAL datastore failed");
131 public void removeXtrIdMapping(XtrIdMapping mapping) {
132 XtrId xtrId = mapping.getMappingRecord().getXtrId();
133 Preconditions.checkNotNull(xtrId, "Make sure you only call addXtrIdMapping when the MappingRecord "
134 + "contains an xTR-ID");
135 if (LOG.isDebugEnabled()) {
136 LOG.debug("MD-SAL: Removing mapping for {}, xTR-ID {}",
137 LispAddressStringifier.getString(mapping.getMappingRecord().getEid()), xtrId);
140 InstanceIdentifier<XtrIdMapping> path = InstanceIdentifierUtil
141 .createXtrIdMappingIid(mapping.getMappingRecord().getEid(), MappingOrigin.Southbound, xtrId);
142 deleteTransaction(path, LogicalDatastoreType.OPERATIONAL,
143 "Deleting xTR-ID mapping from MD-SAL datastore failed");
146 public void removeAllDatastoreContent() {
147 LOG.debug("MD-SAL: Removing all mapping database datastore content (mappings and keys)");
148 removeAllConfigDatastoreContent();
149 removeAllOperationalDatastoreContent();
152 public void removeAllConfigDatastoreContent() {
153 deleteTransaction(DATABASE_ROOT, LogicalDatastoreType.CONFIGURATION,
154 "Removal of all database content in config datastore failed");
157 public void removeAllOperationalDatastoreContent() {
158 deleteTransaction(DATABASE_ROOT, LogicalDatastoreType.OPERATIONAL,
159 "Removal of all database content in operational datastore failed");
162 public void updateAuthenticationKey(AuthenticationKey authenticationKey) {
163 if (LOG.isDebugEnabled()) {
164 LOG.debug("MD-SAL: Updating authentication key for {} with '{}'",
165 LispAddressStringifier.getString(authenticationKey.getEid()),
166 authenticationKey.getMappingAuthkey().getKeyString());
169 InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
170 .createAuthenticationKeyIid(authenticationKey.getEid());
171 writePutTransaction(path, authenticationKey, LogicalDatastoreType.CONFIGURATION,
172 "Updating authentication key in MD-SAL datastore failed");
175 public void updateMapping(Mapping mapping) {
176 if (LOG.isDebugEnabled()) {
177 LOG.debug("MD-SAL: Updating mapping for {}",
178 LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
181 InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
182 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
183 writePutTransaction(path, mapping, getDestinationDatastore(mapping),
184 "Updating mapping in MD-SAL datastore failed");
187 public List<Mapping> getAllMappings() {
188 List<Mapping> mappings = getAllMappings(LogicalDatastoreType.CONFIGURATION);
189 mappings.addAll(getAllMappings(LogicalDatastoreType.OPERATIONAL));
193 public List<Mapping> getAllMappings(LogicalDatastoreType logicalDataStore) {
194 LOG.debug("MD-SAL: Get all mappings from {} datastore",
195 logicalDataStore == LogicalDatastoreType.CONFIGURATION ? "config" : "operational");
196 List<Mapping> mappings = new ArrayList<Mapping>();
197 MappingDatabase mdb = readTransaction(DATABASE_ROOT, logicalDataStore);
199 if (mdb != null && mdb.getVirtualNetworkIdentifier() != null) {
200 for (VirtualNetworkIdentifier id : mdb.getVirtualNetworkIdentifier()) {
201 List<Mapping> ms = id.getMapping();
211 public List<AuthenticationKey> getAllAuthenticationKeys() {
212 LOG.debug("MD-SAL: Get all authentication keys from datastore");
213 List<AuthenticationKey> authKeys = new ArrayList<AuthenticationKey>();
214 MappingDatabase mdb = readTransaction(DATABASE_ROOT, LogicalDatastoreType.CONFIGURATION);
216 if (mdb != null && mdb.getVirtualNetworkIdentifier() != null) {
217 for (VirtualNetworkIdentifier id : mdb.getVirtualNetworkIdentifier()) {
218 List<AuthenticationKey> keys = id.getAuthenticationKey();
220 authKeys.addAll(keys);
228 public void saveLastUpdateTimestamp() {
229 Long timestamp = System.currentTimeMillis();
230 LOG.debug("MD-SAL: Saving last update timestamp to operational datastore: {}", new Date(timestamp).toString());
231 writePutTransaction(LAST_UPDATED, new LastUpdatedBuilder().setLastUpdated(timestamp).build(),
232 LogicalDatastoreType.OPERATIONAL, "Couldn't save last update timestamp to operational datastore");
235 public void removeLastUpdateTimestamp() {
236 LOG.debug("MD-SAL: Removing last update timestamp from operational datastore");
237 deleteTransaction(LAST_UPDATED, LogicalDatastoreType.OPERATIONAL,
238 "Couldn't remove last update timestamp from operational datastore");
241 public Long getLastUpdateTimestamp() {
242 LastUpdated lastUpdated = readTransaction(LAST_UPDATED, LogicalDatastoreType.OPERATIONAL);
243 if (lastUpdated != null && lastUpdated.getLastUpdated() != null) {
244 Long timestamp = lastUpdated.getLastUpdated();
245 LOG.debug("MD-SAL: Retrieved last update timestamp from operational datastore: {}",
246 new Date(timestamp).toString());
249 LOG.debug("MD-SAL: Couldn't retrieve last update timestamp from operational datastore");
254 private static LogicalDatastoreType getDestinationDatastore(Mapping mapping) {
255 return mapping.getOrigin().equals(MappingOrigin.Southbound) ? LogicalDatastoreType.OPERATIONAL
256 : LogicalDatastoreType.CONFIGURATION;
259 private <U extends org.opendaylight.yangtools.yang.binding.DataObject> void writePutTransaction(
260 InstanceIdentifier<U> addIID, U data, LogicalDatastoreType logicalDatastoreType, String errMsg) {
261 WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
262 writeTx.put(logicalDatastoreType, addIID, data, true);
263 Futures.addCallback(writeTx.submit(), new FutureCallback<Void>() {
265 public void onSuccess(Void result) {
268 public void onFailure(Throwable throwable) {
269 LOG.error("Transaction failed:", throwable);
271 }, MoreExecutors.directExecutor());
274 private <U extends org.opendaylight.yangtools.yang.binding.DataObject> U readTransaction(
275 InstanceIdentifier<U> readIID, LogicalDatastoreType logicalDatastoreType) {
276 ReadOnlyTransaction readTx = txChain.newReadOnlyTransaction();
277 CheckedFuture<Optional<U>, ReadFailedException> readFuture = readTx.read(logicalDatastoreType, readIID);
280 Optional<U> optionalDataObject = readFuture.checkedGet();
281 if (optionalDataObject != null && optionalDataObject.isPresent()) {
282 return optionalDataObject.get();
284 LOG.debug("{}: Failed to read", Thread.currentThread().getStackTrace()[1]);
286 } catch (ReadFailedException e) {
287 LOG.warn("Failed to ....", e);
292 private <U extends org.opendaylight.yangtools.yang.binding.DataObject> void deleteTransaction(
293 InstanceIdentifier<U> deleteIID, LogicalDatastoreType logicalDatastoreType, String errMsg) {
295 WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
296 writeTx.delete(logicalDatastoreType, deleteIID);
297 Futures.addCallback(writeTx.submit(), new FutureCallback<Void>() {
299 public void onSuccess(Void result) {
302 public void onFailure(Throwable throwable) {
303 LOG.error("Transaction failed:", throwable);
305 }, MoreExecutors.directExecutor());
308 public void onTransactionChainFailed(TransactionChain<?, ?> chain, AsyncTransaction<?, ?> transaction,
310 LOG.error("Broken chain {} in DataStoreBackEnd, transaction {}, cause {}", chain, transaction.getIdentifier(),
314 public void onTransactionChainSuccessful(TransactionChain<?, ?> chain) {
315 LOG.info("DataStoreBackEnd closed successfully, chain {}", chain);
318 public void closeTransactionChain() {
319 LOG.debug("Closing DataStoreBackEnd transaction chain...");