9ce5f67c1b309dde141c572eada6476f1d583e83
[lispflowmapping.git] / mappingservice / implementation / src / main / java / org / opendaylight / lispflowmapping / implementation / MappingService.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;
9
10 import java.util.Arrays;
11 import java.util.concurrent.Future;
12
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
15 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
16 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
17 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
18 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
19 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
20 import org.opendaylight.lispflowmapping.implementation.config.ConfigIni;
21 import org.opendaylight.lispflowmapping.implementation.mdsal.AuthenticationKeyDataListener;
22 import org.opendaylight.lispflowmapping.implementation.mdsal.DataStoreBackEnd;
23 import org.opendaylight.lispflowmapping.implementation.mdsal.MappingDataListener;
24 import org.opendaylight.lispflowmapping.implementation.util.DSBEInputUtil;
25 import org.opendaylight.lispflowmapping.implementation.util.RPCInputConvertorUtil;
26 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
27 import org.opendaylight.lispflowmapping.interfaces.mappingservice.IMappingService;
28 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eidtolocatorrecords.EidToLocatorRecord;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.LispAddressContainer;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeyInput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddKeyInputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.AddMappingInputBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyInput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyInputBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyOutput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetKeyOutputBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingInputBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingOutput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.GetMappingOutputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingOrigin;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.MappingserviceService;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeyInput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveKeyInputBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingInput;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.RemoveMappingInputBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.SiteId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeyInput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateKeyInputBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingInput;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.UpdateMappingInputBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.mappingservice.rev150906.update.key.input.EidBuilder;
55 import org.opendaylight.yangtools.yang.common.RpcError;
56 import org.opendaylight.yangtools.yang.common.RpcResult;
57 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61 import com.google.common.base.Preconditions;
62 import com.google.common.util.concurrent.Futures;
63
64 /**
65  * Dispatcher of API calls that implements the RPC and Java APIs in mappingservice.yang and IMappingService
66  * respectively. It also coordinates and acts as container for all objects in charge of
67  *  - saving and updating md-sal datastore stored mappings
68  *  - monitoring md-sal datastore mapping updates and pushing them to the in memory mapping-system
69  *  - in memory mapping-system
70  *
71  * @author Lorand Jakab
72  * @author Florin Coras
73  *
74  */
75 public class MappingService implements MappingserviceService, IMappingService, BindingAwareProvider, AutoCloseable {
76     protected static final Logger LOG = LoggerFactory.getLogger(MappingService.class);
77     private static final String NOT_FOUND_TAG = "data-missing";
78     private static final String DATA_EXISTS_TAG = "data-exists";
79
80     private MappingSystem mappingSystem;
81     private DataStoreBackEnd dsbe;
82     private RpcRegistration<MappingserviceService> mappingServiceRpc;
83     private AuthenticationKeyDataListener keyListener;
84     private MappingDataListener mappingListener;
85     private ILispDAO dao;
86
87     private DataBroker dataBroker;
88     private RpcProviderRegistry rpcRegistry;
89     private BindingAwareBroker bindingAwareBroker;
90     private NotificationPublishService notificationPublishService;
91
92     private static final ConfigIni configIni = new ConfigIni();
93     private boolean overwritePolicy = configIni.mappingOverwriteIsSet();
94     private boolean notificationPolicy = configIni.smrIsSet();
95     private boolean iterateMask = true;
96
97     public MappingService() {
98         LOG.debug("MappingService created!");
99     }
100
101     public void setDataBroker(DataBroker dataBroker) {
102         this.dataBroker = dataBroker;
103     }
104
105     public void setRpcProviderRegistry(RpcProviderRegistry rpc) {
106         this.rpcRegistry = rpc;
107     }
108
109     public void setBindingAwareBroker(BindingAwareBroker broker) {
110         this.bindingAwareBroker = broker;
111     }
112
113     public void setNotificationPublishService(NotificationPublishService nps) {
114         this.notificationPublishService = nps;
115     }
116
117     public void setDaoService(ILispDAO dao) {
118         this.dao = dao;
119     }
120
121     @Override
122     public void setMappingOverwrite(boolean overwrite) {
123         this.overwritePolicy = overwrite;
124         if (mappingSystem != null) {
125             mappingSystem.setOverwritePolicy(overwrite);
126         }
127     }
128
129     public void initialize() {
130         bindingAwareBroker.registerProvider(this);
131
132         mappingServiceRpc = rpcRegistry.addRpcImplementation(MappingserviceService.class, this);
133         dsbe = new DataStoreBackEnd(dataBroker);
134
135         mappingSystem = new MappingSystem(dao, iterateMask, notificationPolicy, overwritePolicy);
136         mappingSystem.setDataStoreBackEnd(dsbe);
137         mappingSystem.initialize();
138
139         keyListener = new AuthenticationKeyDataListener(dataBroker, mappingSystem);
140         mappingListener = new MappingDataListener(dataBroker, mappingSystem, notificationPublishService);
141     }
142
143     @Override
144     public Future<RpcResult<Void>> addKey(AddKeyInput input) {
145         Preconditions.checkNotNull(input, "add-key RPC input must be not null!");
146         LOG.trace("RPC received to add the following key: " + input.toString());
147
148         RpcResultBuilder<Void> rpcResultBuilder;
149
150         // XXX: to remove once RPC API has been updated to remove explicit mask
151         input = new AddKeyInputBuilder(input).setLispAddressContainer(
152                 MaskUtil.fixMask(input.getLispAddressContainer(), input.getMaskLength())).build();
153
154         String key = mappingSystem.getAuthenticationKey(input.getLispAddressContainer());
155
156         if (key != null) {
157             String message = "Key already exists! Please use update-key if you want to change it.";
158             rpcResultBuilder = RpcResultBuilder.<Void>failed()
159                     .withError(RpcError.ErrorType.PROTOCOL, DATA_EXISTS_TAG, message);
160             return Futures.immediateFuture(rpcResultBuilder.build());
161         }
162
163         dsbe.addAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
164         rpcResultBuilder = RpcResultBuilder.success();
165
166         return Futures.immediateFuture(rpcResultBuilder.build());
167     }
168
169     @Override
170     public Future<RpcResult<Void>> addMapping(AddMappingInput input) {
171         Preconditions.checkNotNull(input, "add-mapping RPC input must be not null!");
172         LOG.trace("RPC received to add the following mapping: " + input.toString());
173
174         // XXX: to remove once RPC API has been updated to remove explicit mask
175         input = new AddMappingInputBuilder(input).setLispAddressContainer(
176                 MaskUtil.fixMask(input.getLispAddressContainer(), input.getMaskLength())).build();
177
178         dsbe.addMapping(RPCInputConvertorUtil.toMapping(input));
179
180         RpcResultBuilder<Void> rpcResultBuilder;
181
182         rpcResultBuilder = RpcResultBuilder.success();
183
184         return Futures.immediateFuture(rpcResultBuilder.build());
185     }
186
187     @Override
188     public Future<RpcResult<GetKeyOutput>> getKey(GetKeyInput input) {
189         Preconditions.checkNotNull(input, "get-key RPC input must be not null!");
190         LOG.trace("RPC received to get the following key: " + input.toString());
191
192         // XXX: to remove once RPC API has been updated to remove explicit mask
193         input = new GetKeyInputBuilder(input).setLispAddressContainer(
194                 MaskUtil.fixMask(input.getLispAddressContainer(), input.getMaskLength())).build();
195
196         RpcResultBuilder<GetKeyOutput> rpcResultBuilder;
197
198         String key = mappingSystem.getAuthenticationKey(input.getLispAddressContainer());
199
200         if (key == null) {
201             String message = "Key was not found in the mapping database";
202             rpcResultBuilder = RpcResultBuilder.<GetKeyOutput>failed()
203                     .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
204         } else {
205             rpcResultBuilder = RpcResultBuilder.success(new GetKeyOutputBuilder().setAuthkey(key));
206         }
207
208         return Futures.immediateFuture(rpcResultBuilder.build());
209     }
210
211     @Override
212     public Future<RpcResult<GetMappingOutput>> getMapping(GetMappingInput input) {
213         Preconditions.checkNotNull(input, "get-mapping RPC input must be not null!");
214         LOG.trace("RPC received to get the following mapping: " + input.toString());
215
216         // XXX: to remove once RPC API has been updated to remove explicit mask
217         input = new GetMappingInputBuilder(input).setLispAddressContainer(
218                 MaskUtil.fixMask(input.getLispAddressContainer(), input.getMaskLength())).build();
219
220         RpcResultBuilder<GetMappingOutput> rpcResultBuilder;
221
222         EidToLocatorRecord reply = (EidToLocatorRecord) mappingSystem.getMapping(input.getLispAddressContainer());
223
224         if (reply == null) {
225             String message = "No mapping was found in the mapping database";
226             rpcResultBuilder = RpcResultBuilder.<GetMappingOutput>failed()
227                     .withError(RpcError.ErrorType.APPLICATION, NOT_FOUND_TAG, message);
228         } else {
229             rpcResultBuilder = RpcResultBuilder.success(new GetMappingOutputBuilder().setEidToLocatorRecord(Arrays
230                     .asList(reply)));
231         }
232
233         return Futures.immediateFuture(rpcResultBuilder.build());
234     }
235
236     @Override
237     public Future<RpcResult<Void>> removeKey(RemoveKeyInput input) {
238         Preconditions.checkNotNull(input, "remove-key RPC input must be not null!");
239         LOG.trace("RPC received to remove the following key: " + input.toString());
240
241         // XXX: to remove once RPC API has been updated to remove explicit mask
242         input = new RemoveKeyInputBuilder(input).setLispAddressContainer(
243                 MaskUtil.fixMask(input.getLispAddressContainer(), input.getMaskLength())).build();
244
245         RpcResultBuilder<Void> rpcResultBuilder;
246
247         dsbe.removeAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
248
249         rpcResultBuilder = RpcResultBuilder.success();
250
251         return Futures.immediateFuture(rpcResultBuilder.build());
252     }
253
254     @Override
255     public Future<RpcResult<Void>> removeMapping(RemoveMappingInput input) {
256         Preconditions.checkNotNull(input, "remove-mapping RPC input must be not null!");
257         LOG.trace("RPC received to remove the following mapping: " + input.toString());
258
259         // XXX: to remove once RPC API has been updated to remove explicit mask
260         input = new RemoveMappingInputBuilder(input).setLispAddressContainer(
261                 MaskUtil.fixMask(input.getLispAddressContainer(), input.getMaskLength())).build();
262
263         RpcResultBuilder<Void> rpcResultBuilder;
264
265         dsbe.removeMapping(RPCInputConvertorUtil.toMapping(input));
266
267         rpcResultBuilder = RpcResultBuilder.success();
268
269         return Futures.immediateFuture(rpcResultBuilder.build());
270     }
271
272     @Override
273     public Future<RpcResult<Void>> updateKey(UpdateKeyInput input) {
274         Preconditions.checkNotNull(input, "update-key RPC input must be not null!");
275         LOG.trace("RPC received to update the following key: " + input.toString());
276
277         // XXX: to remove once RPC API has been updated to remove explicit mask
278         input = new UpdateKeyInputBuilder(input).setEid(
279                 new EidBuilder(input.getEid()).setLispAddressContainer(
280                         MaskUtil.fixMask(input.getEid().getLispAddressContainer(), input.getEid()
281                                 .getMaskLength())).build()).build();
282
283         RpcResultBuilder<Void> rpcResultBuilder;
284
285         String key = mappingSystem.getAuthenticationKey(input.getEid().getLispAddressContainer());
286
287         if (key == null) {
288             String message = "Key doesn't exist! Please use add-key if you want to create a new authentication key.";
289             rpcResultBuilder = RpcResultBuilder.<Void>failed()
290                     .withError(RpcError.ErrorType.PROTOCOL, NOT_FOUND_TAG, message);
291             return Futures.immediateFuture(rpcResultBuilder.build());
292         }
293
294         dsbe.updateAuthenticationKey(RPCInputConvertorUtil.toAuthenticationKey(input));
295         rpcResultBuilder = RpcResultBuilder.success();
296
297         return Futures.immediateFuture(rpcResultBuilder.build());
298     }
299
300     @Override
301     public Future<RpcResult<Void>> updateMapping(UpdateMappingInput input) {
302         LOG.trace("RPC received to update the following mapping: " + input.toString());
303         Preconditions.checkNotNull(input, "update-mapping RPC input must be not null!");
304
305         // XXX: to remove once RPC API has been updated to remove explicit mask
306         input = new UpdateMappingInputBuilder(input).setLispAddressContainer(
307                 MaskUtil.fixMask(input.getLispAddressContainer(), input.getMaskLength())).build();
308
309         RpcResultBuilder<Void> rpcResultBuilder;
310
311         dsbe.updateMapping(RPCInputConvertorUtil.toMapping(input));
312
313         rpcResultBuilder = RpcResultBuilder.success();
314
315         return Futures.immediateFuture(rpcResultBuilder.build());
316     }
317
318     @Override
319     public void addMapping(MappingOrigin origin, LispAddressContainer key, SiteId siteId, Object data) {
320         dsbe.addMapping(DSBEInputUtil.toMapping(origin, key, siteId, (EidToLocatorRecord) data));
321         mappingSystem.updateMappingRegistration(origin, key);
322     }
323
324     @Override
325     public Object getMapping(MappingOrigin origin, LispAddressContainer key) {
326         return mappingSystem.getMapping(origin, key);
327     }
328
329     @Override
330     public Object getMapping(LispAddressContainer key) {
331         return mappingSystem.getMapping(key);
332     }
333
334     @Override
335     public Object getMapping(LispAddressContainer srcKey, LispAddressContainer dstKey) {
336         return mappingSystem.getMapping(srcKey, dstKey);
337     }
338
339     @Override
340     public void removeMapping(MappingOrigin origin, LispAddressContainer key) {
341         dsbe.removeMapping(DSBEInputUtil.toMapping(origin, key));
342     }
343
344     @Override
345     public void addAuthenticationKey(LispAddressContainer key, String authKey) {
346         dsbe.addAuthenticationKey(DSBEInputUtil.toAuthenticationKey(key, authKey));
347     }
348
349     @Override
350     public String getAuthenticationKey(LispAddressContainer key) {
351         return mappingSystem.getAuthenticationKey(key);
352     }
353
354     @Override
355     public void removeAuthenticationKey(LispAddressContainer key) {
356         dsbe.removeAuthenticationKey(DSBEInputUtil.toAuthenticationKey(key, null));
357     }
358
359     @Override
360     public void addData(MappingOrigin origin, LispAddressContainer key, String subKey, Object data) {
361         mappingSystem.addData(origin, key, subKey, data);
362     }
363
364     @Override
365     public Object getData(MappingOrigin origin, LispAddressContainer key, String subKey) {
366         return mappingSystem.getData(origin, key, subKey);
367     }
368
369     @Override
370     public void removeData(MappingOrigin origin, LispAddressContainer key, String subKey) {
371         mappingSystem.removeData(origin, key, subKey);
372     }
373
374     @Override
375     public String printMappings() {
376         return mappingSystem.printMappings();
377     }
378
379     @Override
380     public void onSessionInitiated(ProviderContext session) {
381         LOG.info("Mapping Service provider session initializing!");
382     }
383
384     @Override
385     public void close() throws Exception {
386         LOG.info("Mapping Service is being destroyed!");
387         mappingServiceRpc.close();
388         keyListener.closeDataChangeListener();
389         mappingListener.closeDataChangeListener();
390     }
391
392     @Override
393     public void cleanCachedMappings() {
394         mappingSystem.cleanCaches();
395         dsbe.removeAllMappings();
396     }
397 }