9d2d2a351f4255eb568d0c64269c15c16c30ff16
[lispflowmapping.git] / mappingservice / dsbackend / src / main / java / org / opendaylight / lispflowmapping / dsbackend / 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.dsbackend;
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.lisp.util.LispAddressStringifier;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
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.db.instance.mapping.XtrIdMapping;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.mapping.database.VirtualNetworkIdentifier;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 import com.google.common.base.Optional;
35 import com.google.common.base.Preconditions;
36 import com.google.common.util.concurrent.CheckedFuture;
37 import com.google.common.util.concurrent.FutureCallback;
38 import com.google.common.util.concurrent.Futures;
39
40 /**
41  * Stores data coming from the mapping database RPCs into the MD-SAL datastore.
42  *
43  * @author Lorand Jakab
44  *
45  */
46 public class DataStoreBackEnd implements TransactionChainListener {
47     protected static final Logger LOG = LoggerFactory.getLogger(DataStoreBackEnd.class);
48     private static final InstanceIdentifier<MappingDatabase> DATABASE_ROOT =
49             InstanceIdentifier.create(MappingDatabase.class);
50     private BindingTransactionChain txChain;
51
52     public DataStoreBackEnd(DataBroker broker) {
53         this.txChain = broker.createTransactionChain(this);
54     }
55
56
57     public void addAuthenticationKey(AuthenticationKey authenticationKey) {
58         if (LOG.isDebugEnabled()) {
59             LOG.debug("MD-SAL: Adding authentication key '{}' for {}",
60                     authenticationKey.getMappingAuthkey().getKeyString(),
61                     LispAddressStringifier.getString(authenticationKey.getEid()));
62         }
63
64         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
65                 .createAuthenticationKeyIid(authenticationKey.getEid());
66         writePutTransaction(path, authenticationKey, LogicalDatastoreType.CONFIGURATION,
67                 "Adding authentication key to MD-SAL datastore failed");
68     }
69
70     public void addMapping(Mapping mapping) {
71         if (LOG.isDebugEnabled()) {
72             LOG.debug("MD-SAL: Adding mapping for {}",
73                     LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
74         }
75
76         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
77                 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
78         writePutTransaction(path, mapping, getDestinationDatastore(mapping),
79                 "Adding mapping to MD-SAL datastore failed");
80     }
81
82     // This method assumes that it is only called for southbound originated Map-Registers
83     public void addXtrIdMapping(XtrIdMapping mapping) {
84         XtrId xtrId = mapping.getMappingRecord().getXtrId();
85         Preconditions.checkNotNull(xtrId, "Make sure you only call addXtrIdMapping when the MappingRecord "
86                 + "contains an xTR-ID");
87         if (LOG.isDebugEnabled()) {
88             LOG.debug("MD-SAL: Adding mapping for {}, xTR-ID {}",
89                     LispAddressStringifier.getString(mapping.getMappingRecord().getEid()), xtrId);
90         }
91
92         InstanceIdentifier<XtrIdMapping> path = InstanceIdentifierUtil
93                 .createXtrIdMappingIid(mapping.getMappingRecord().getEid(), MappingOrigin.Southbound, xtrId);
94         writePutTransaction(path, mapping, LogicalDatastoreType.OPERATIONAL,
95                 "Adding xTR-ID mapping to MD-SAL datastore failed");
96     }
97
98     public void removeAuthenticationKey(AuthenticationKey authenticationKey) {
99         if (LOG.isDebugEnabled()) {
100             LOG.debug("MD-SAL: Removing authentication key for {}",
101                     LispAddressStringifier.getString(authenticationKey.getEid()));
102         }
103
104         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
105                 .createAuthenticationKeyIid(authenticationKey.getEid());
106         deleteTransaction(path, LogicalDatastoreType.CONFIGURATION,
107                 "Deleting authentication key from MD-SAL datastore failed");
108     }
109
110     public void removeMapping(Mapping mapping) {
111         if (LOG.isDebugEnabled()) {
112             LOG.debug("MD-SAL: Removing mapping for {}",
113                     LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
114         }
115
116         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
117                 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
118         deleteTransaction(path, getDestinationDatastore(mapping), "Deleting mapping from MD-SAL datastore failed");
119     }
120
121     public void removeXtrIdMapping(XtrIdMapping mapping) {
122         XtrId xtrId = mapping.getMappingRecord().getXtrId();
123         Preconditions.checkNotNull(xtrId, "Make sure you only call addXtrIdMapping when the MappingRecord "
124                 + "contains an xTR-ID");
125         if (LOG.isDebugEnabled()) {
126             LOG.debug("MD-SAL: Removing mapping for {}, xTR-ID {}",
127                     LispAddressStringifier.getString(mapping.getMappingRecord().getEid()), xtrId);
128         }
129
130         InstanceIdentifier<XtrIdMapping> path = InstanceIdentifierUtil
131                 .createXtrIdMappingIid(mapping.getMappingRecord().getEid(), MappingOrigin.Southbound, xtrId);
132         deleteTransaction(path, LogicalDatastoreType.OPERATIONAL,
133                 "Deleting xTR-ID mapping from MD-SAL datastore failed");
134     }
135
136     public void removeAllDatastoreContent() {
137         LOG.debug("MD-SAL: Removing all mapping database datastore content (mappings and keys)");
138         removeAllConfigDatastoreContent();
139         removeAllOperationalDatastoreContent();
140     }
141
142     public void removeAllConfigDatastoreContent() {
143         deleteTransaction(DATABASE_ROOT, LogicalDatastoreType.CONFIGURATION,
144                 "Removal of all database content in config datastore failed");
145     }
146
147     public void removeAllOperationalDatastoreContent() {
148         deleteTransaction(DATABASE_ROOT, LogicalDatastoreType.OPERATIONAL,
149                 "Removal of all database content in operational datastore failed");
150     }
151
152     public void updateAuthenticationKey(AuthenticationKey authenticationKey) {
153         if (LOG.isDebugEnabled()) {
154             LOG.debug("MD-SAL: Updating authentication key for {} with '{}'",
155                     LispAddressStringifier.getString(authenticationKey.getEid()),
156                     authenticationKey.getMappingAuthkey().getKeyString());
157         }
158
159         InstanceIdentifier<AuthenticationKey> path = InstanceIdentifierUtil
160                 .createAuthenticationKeyIid(authenticationKey.getEid());
161         writePutTransaction(path, authenticationKey, LogicalDatastoreType.CONFIGURATION,
162                 "Updating authentication key in MD-SAL datastore failed");
163     }
164
165     public void updateMapping(Mapping mapping) {
166         if (LOG.isDebugEnabled()) {
167             LOG.debug("MD-SAL: Updating mapping for {}",
168                     LispAddressStringifier.getString(mapping.getMappingRecord().getEid()));
169         }
170
171         InstanceIdentifier<Mapping> path = InstanceIdentifierUtil
172                 .createMappingIid(mapping.getMappingRecord().getEid(), mapping.getOrigin());
173         writePutTransaction(path, mapping, getDestinationDatastore(mapping),
174                 "Updating mapping in MD-SAL datastore failed");
175     }
176
177     public List<Mapping> getAllMappings() {
178         List<Mapping> mappings = getAllMappings(LogicalDatastoreType.CONFIGURATION);
179         mappings.addAll(getAllMappings(LogicalDatastoreType.OPERATIONAL));
180         return mappings;
181     }
182
183     public List<Mapping> getAllMappings(LogicalDatastoreType logicalDataStore) {
184         LOG.debug("MD-SAL: Get all mappings from datastore");
185         List<Mapping> mappings = new ArrayList<Mapping>();
186         MappingDatabase mdb = readTransaction(DATABASE_ROOT, logicalDataStore);
187
188         if (mdb != null) {
189             for (VirtualNetworkIdentifier id : mdb.getVirtualNetworkIdentifier()) {
190                 List<Mapping> ms = id.getMapping();
191                 if (ms != null) {
192                     mappings.addAll(ms);
193                 }
194             }
195         }
196
197         return mappings;
198     }
199
200     public List<AuthenticationKey> getAllAuthenticationKeys() {
201         LOG.debug("MD-SAL: Get all authentication keys from datastore");
202         List<AuthenticationKey> authKeys = new ArrayList<AuthenticationKey>();
203         MappingDatabase mdb = readTransaction(DATABASE_ROOT, LogicalDatastoreType.CONFIGURATION);
204
205         if (mdb != null) {
206             for (VirtualNetworkIdentifier id : mdb.getVirtualNetworkIdentifier()) {
207                 List<AuthenticationKey> keys = id.getAuthenticationKey();
208                 if (keys != null) {
209                     authKeys.addAll(keys);
210                 }
211             }
212         }
213
214         return authKeys;
215     }
216
217     private static LogicalDatastoreType getDestinationDatastore(Mapping mapping) {
218         return mapping.getOrigin().equals(MappingOrigin.Southbound) ? LogicalDatastoreType.OPERATIONAL
219                 : LogicalDatastoreType.CONFIGURATION;
220     }
221
222     private <U extends org.opendaylight.yangtools.yang.binding.DataObject> void writePutTransaction(
223             InstanceIdentifier<U> addIID, U data, LogicalDatastoreType logicalDatastoreType, String errMsg) {
224         WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
225         writeTx.put(logicalDatastoreType, addIID, data, true);
226         Futures.addCallback(writeTx.submit(), new FutureCallback<Void>() {
227
228             public void onSuccess(Void result) {
229             }
230
231             public void onFailure(Throwable t) {
232                 LOG.error("Transaction failed:", t);
233             }
234         });
235     }
236
237     private <U extends org.opendaylight.yangtools.yang.binding.DataObject> U readTransaction(
238             InstanceIdentifier<U> readIID, LogicalDatastoreType logicalDatastoreType) {
239         ReadOnlyTransaction readTx = txChain.newReadOnlyTransaction();
240         CheckedFuture<Optional<U>, ReadFailedException> readFuture = readTx.read(logicalDatastoreType, readIID);
241         readTx.close();
242         try {
243             Optional<U> optionalDataObject = readFuture.checkedGet();
244             if (optionalDataObject != null && optionalDataObject.isPresent()) {
245                 return optionalDataObject.get();
246             } else {
247                 LOG.debug("{}: Failed to read", Thread.currentThread().getStackTrace()[1]);
248             }
249         } catch (ReadFailedException e) {
250             LOG.warn("Failed to ....", e);
251         }
252         return null;
253     }
254
255     private <U extends org.opendaylight.yangtools.yang.binding.DataObject> void deleteTransaction(
256             InstanceIdentifier<U> deleteIID, LogicalDatastoreType logicalDatastoreType, String errMsg) {
257
258         WriteTransaction writeTx = txChain.newWriteOnlyTransaction();
259         writeTx.delete(logicalDatastoreType, deleteIID);
260         Futures.addCallback(writeTx.submit(), new FutureCallback<Void>() {
261
262             public void onSuccess(Void result) {
263             }
264
265             public void onFailure(Throwable t) {
266                 LOG.error("Transaction failed:", t);
267             }
268         });
269     }
270
271     public void onTransactionChainFailed(TransactionChain<?, ?> chain, AsyncTransaction<?, ?> transaction,
272             Throwable cause) {
273         LOG.error("Broken chain {} in DataStoreBackEnd, transaction {}, cause {}", chain, transaction.getIdentifier(),
274                 cause);
275     }
276
277     public void onTransactionChainSuccessful(TransactionChain<?, ?> chain) {
278         LOG.info("DataStoreBackEnd closed successfully, chain {}", chain);
279     }
280 }