Magnesium platform upgrade
[lispflowmapping.git] / mappingservice / config / src / main / java / org / opendaylight / lispflowmapping / config / ConfigIni.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  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.config;
9
10 import java.util.concurrent.TimeUnit;
11 import org.opendaylight.lispflowmapping.interfaces.mappingservice.IMappingService;
12 import org.osgi.framework.Bundle;
13 import org.osgi.framework.BundleContext;
14 import org.osgi.framework.FrameworkUtil;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
17
18 public final class ConfigIni {
19
20     private static final Logger LOG = LoggerFactory.getLogger(ConfigIni.class);
21     private boolean mappingMerge;
22     private boolean smr;
23     private String elpPolicy;
24     private IMappingService.LookupPolicy lookupPolicy;
25     private long registrationValiditySb;
26     private long smrTimeout;
27     private int smrRetryCount;
28     private boolean authEnabled;
29     private int negativeMappingTTL;
30     private int numberOfBucketsInTimeBucketWheel;
31
32     /*
33      * XXX  When configuration options are added or removed, they should also be added/removed in the karaf
34      * `etc/custom.properties file`, hosted in the odlparent repository [0]. The "Configuring LISP Flow Mapping"
35      * section in the LISP Flow Mapping User Guide [1] has to be updated too, including when a configuration option's
36      * semantics or behavior is changed, in addition to having added/removed and option. Since we don't document
37      * options extensively in this file, the User Guide is the canonical documentation for them.
38      *
39      * [0] https://git.opendaylight.org/gerrit/gitweb?p=odlparent.git;a=blob;f=karaf/opendaylight-karaf-resources/src/main/resources/etc/custom.properties
40      * [1] https://git.opendaylight.org/gerrit/gitweb?p=docs.git;a=blob;f=docs/user-guide/lisp-flow-mapping-user-guide.rst
41      */
42     private static final String LISP_LOOKUP_POLICY = "lisp.lookupPolicy";
43     private static final String LISP_MAPPING_MERGE = "lisp.mappingMerge";
44     private static final String LISP_SMR = "lisp.smr";
45     private static final String LISP_ELP_POLICY = "lisp.elpPolicy";
46     private static final String LISP_REGISTER_VALIDITY_SB = "lisp.registerValiditySb";
47     private static final String LISP_SMR_RETRY_COUNT = "lisp.smrRetryCount";
48     private static final String LISP_SMR_TIMEOUT = "lisp.smrTimeout";
49     private static final String LISP_AUTH_ENABLED = "lisp.authEnabled";
50     private static final String LISP_NEGATIVE_MAPPING_TTL = "lisp.negativeMappingTTL";
51
52     // SB Map Register validity period in milliseconds. Default is 3.3 minutes.
53     private static final long MIN_REGISTRATION_VALIDITY_SB = 200000L;
54     private static final long DEFAULT_SMR_TIMEOUT = 3000L;
55     private static final int DEFAULT_SMR_RETRY_COUNT = 5;
56     private static final int DEFAULT_NEGATIVE_MAPPING_TTL = 15;
57     private static final int MIN_NUMBER_OF_BUCKETS_IN_TIME_BUCKET_WHEEL = 2;
58     private static final int TIMEOUT_TOLERANCE_MULTIPLIER_IN_TIME_BUCKET_WHEEL = 2;
59
60     private static final ConfigIni INSTANCE = new ConfigIni();
61
62     private ConfigIni() {
63         Bundle bundle = FrameworkUtil.getBundle(this.getClass());
64         BundleContext context = null;
65         if (bundle != null) {
66             context = bundle.getBundleContext();
67             if (context == null) {
68                 LOG.warn("Couldn't get the BundleContext needed for reading the properties in the configuration file, "
69                         + "bundle state is '{}'", bundleStateToString(bundle.getState()));
70             }
71         } else {
72             LOG.warn("Couldn't get the Bundle object needed for reading the properties in the configuration file, "
73                     + "using built-in defaults");
74         }
75
76         initConfigs(context);
77     }
78
79     private void initConfigs(BundleContext context) {
80         initMappingMerge(context);
81         initSmr(context);
82         initElpPolicy(context);
83         initLookupPolicy(context);
84         initRegisterValiditySb(context);
85         initSmrRetryCount(context);
86         initSmrTimeout(context);
87         initAuthEnabled(context);
88         initNegativeMappingTTL(context);
89         initBucketNumber();
90     }
91
92     private String bundleStateToString(int state) {
93         switch (state) {
94             case Bundle.ACTIVE:
95                 return "Active";
96             case Bundle.INSTALLED:
97                 return "Installed";
98             case Bundle.RESOLVED:
99                 return "Resolved";
100             case Bundle.STARTING:
101                 return "Starting";
102             case Bundle.STOPPING:
103                 return "Stopping";
104             case Bundle.UNINSTALLED:
105                 return "Uninstalled";
106             default:
107                 return "_Unknown_";
108         }
109     }
110
111     private void initRegisterValiditySb(BundleContext context) {
112         // set the default value first
113         this.registrationValiditySb = MIN_REGISTRATION_VALIDITY_SB;
114
115         String str = null;
116
117         if (context != null) {
118             str = context.getProperty(LISP_REGISTER_VALIDITY_SB);
119         }
120
121         if (str == null) {
122             str = System.getProperty(LISP_REGISTER_VALIDITY_SB);
123             if (str == null) {
124                 LOG.debug("Configuration variable '{}' is unset. Setting to default value: '3.33 minutes' ",
125                         LISP_REGISTER_VALIDITY_SB);
126                 return;
127             }
128         }
129
130         try {
131             final long regValidity = Long.parseLong(str.trim());
132             setRegistrationValiditySb(regValidity);
133         } catch (NumberFormatException e) {
134             this.registrationValiditySb = MIN_REGISTRATION_VALIDITY_SB;
135             LOG.debug("Configuration variable 'registerValiditySb' was not set correctly. Registration validity for"
136                     + "South Bound Map Registers is set to default value of 3.3 minutes");
137         }
138     }
139
140     private void initLookupPolicy(BundleContext context) {
141         // set the default value first
142         this.lookupPolicy = IMappingService.LookupPolicy.NB_FIRST;
143
144         String str = null;
145
146         if (context != null) {
147             str = context.getProperty(LISP_LOOKUP_POLICY);
148         }
149
150         if (str == null) {
151             str = System.getProperty(LISP_LOOKUP_POLICY);
152             if (str == null) {
153                 LOG.debug("Configuration variable '{}' is unset. Setting to default value: 'northboundFirst' "
154                         + "(Southbound is only looked up if Northbound is empty) ", LISP_LOOKUP_POLICY);
155                 return;
156             }
157         }
158
159         if (str.trim().equalsIgnoreCase("northboundAndSouthbound")) {
160             this.lookupPolicy = IMappingService.LookupPolicy.NB_AND_SB;
161             LOG.debug("Setting configuration variable '{}' to 'northboundAndSouthbound' (Southbound is always "
162                     + "looked up and can filter Northbound if intersection is not empty)", LISP_LOOKUP_POLICY);
163         } else {
164             LOG.debug("Setting configuration variable '{}' to 'northboundFirst' (Southbound is only looked up "
165                     + "if Northbound is empty)", LISP_LOOKUP_POLICY);
166         }
167     }
168
169     private void initMappingMerge(BundleContext context) {
170         // set the default value first
171         this.mappingMerge = false;
172
173         String str = null;
174
175         if (context != null) {
176             str = context.getProperty(LISP_MAPPING_MERGE);
177         }
178
179         if (str == null) {
180             str = System.getProperty(LISP_MAPPING_MERGE);
181             if (str == null) {
182                 LOG.debug("Configuration variable '{}' is unset. Setting to default value: 'false'",
183                         LISP_MAPPING_MERGE);
184                 return;
185             }
186         }
187
188         if (str.trim().equalsIgnoreCase("true")) {
189             this.mappingMerge = true;
190             LOG.debug("Setting configuration variable '{}' to 'true'", LISP_MAPPING_MERGE);
191         } else {
192             LOG.debug("Setting configuration variable '{}' to 'false'", LISP_MAPPING_MERGE);
193         }
194     }
195
196     private void initSmr(BundleContext context) {
197         // set the default value first
198         this.smr = true;
199
200         String str = null;
201
202         if (context != null) {
203             str = context.getProperty(LISP_SMR);
204         }
205
206         if (str == null) {
207             str = System.getProperty(LISP_SMR);
208             if (str == null) {
209                 LOG.debug("Configuration variable '{}' is unset. Setting to default value: 'true'", LISP_SMR);
210                 return;
211             }
212         }
213
214         if (str.trim().equalsIgnoreCase("false")) {
215             this.smr = false;
216             LOG.debug("Setting configuration variable '{}' to 'false'", LISP_SMR);
217         } else {
218             LOG.debug("Setting configuration variable '{}' to 'true'", LISP_SMR);
219         }
220     }
221
222     private void initElpPolicy(BundleContext context) {
223         // set the default value first
224         this.elpPolicy = "default";
225
226         String str = null;
227
228         if (context != null) {
229             str = context.getProperty(LISP_ELP_POLICY);
230         }
231
232         if (str == null) {
233             str = System.getProperty(LISP_ELP_POLICY);
234             if (str == null) {
235                 LOG.debug("Configuration variable '{}' is unset. Setting to default value: 'default' (ELP only)",
236                         LISP_ELP_POLICY);
237                 return;
238             }
239         }
240
241         if (str.trim().equalsIgnoreCase("both")) {
242             this.elpPolicy = "both";
243             LOG.debug("Setting configuration variable '{}' to 'both' (keep ELP, add next hop)", LISP_ELP_POLICY);
244         } else if (str.trim().equalsIgnoreCase("replace")) {
245             this.elpPolicy = "replace";
246             LOG.debug("Setting configuration variable '{}' to 'replace' (next hop only)", LISP_ELP_POLICY);
247         } else {
248             LOG.debug("Setting configuration variable '{}' to 'default' (ELP only)", LISP_ELP_POLICY);
249         }
250     }
251
252     private void initSmrRetryCount(BundleContext context) {
253         // set the default value first
254         this.smrRetryCount = DEFAULT_SMR_RETRY_COUNT;
255
256         String str = null;
257
258         if (context != null) {
259             str = context.getProperty(LISP_SMR_RETRY_COUNT);
260         }
261
262         if (str == null) {
263             str = System.getProperty(LISP_SMR_RETRY_COUNT);
264             if (str == null) {
265                 LOG.debug("Configuration variable '{}' is unset. Setting to default value: '{}'", LISP_SMR_RETRY_COUNT,
266                         smrRetryCount);
267                 return;
268             }
269         }
270
271         try {
272             this.smrRetryCount = Integer.parseInt(str);
273             LOG.debug("Setting configuration variable '{}' to '{}'", LISP_SMR_RETRY_COUNT, smrRetryCount);
274         } catch (NumberFormatException e) {
275             LOG.debug("Configuration variable '{}' was not set correctly. SMR retry count "
276                     + "is set to default value ({})", LISP_SMR_RETRY_COUNT, smrRetryCount);
277         }
278     }
279
280     private void initSmrTimeout(BundleContext context) {
281         // set the default value first
282         this.smrTimeout = DEFAULT_SMR_TIMEOUT;
283
284         String str = null;
285
286         if (context != null) {
287             str = context.getProperty(LISP_SMR_TIMEOUT);
288         }
289
290         if (str == null) {
291             str = System.getProperty(LISP_SMR_TIMEOUT);
292             if (str == null) {
293                 LOG.debug("Configuration variable '{}' is unset. Setting to default value: '{}'", LISP_SMR_TIMEOUT,
294                         smrTimeout);
295                 return;
296             }
297         }
298
299         try {
300             this.smrTimeout = Long.parseLong(str);
301             LOG.debug("Setting configuration variable '{}' to '{}'", LISP_SMR_TIMEOUT, smrTimeout);
302         } catch (NumberFormatException e) {
303             LOG.debug("Configuration variable '{}' was not set correctly. SMR timeout "
304                     + "is set to default value ({})", LISP_SMR_TIMEOUT, smrTimeout);
305         }
306     }
307
308     private void initAuthEnabled(BundleContext context) {
309         // set the default value first
310         this.authEnabled = true;
311
312         String str = null;
313
314         if (context != null) {
315             str = context.getProperty(LISP_AUTH_ENABLED);
316         }
317
318         if (str == null) {
319             str = System.getProperty(LISP_AUTH_ENABLED);
320             if (str == null) {
321                 LOG.debug("Configuration variable '{}' is unset. Setting to default value: 'true'", LISP_AUTH_ENABLED);
322                 return;
323             }
324         }
325
326         if (str.trim().equalsIgnoreCase("false")) {
327             this.authEnabled = false;
328             LOG.debug("Setting configuration variable '{}' to 'false'", LISP_AUTH_ENABLED);
329         } else {
330             LOG.debug("Setting configuration variable '{}' to 'true'", LISP_AUTH_ENABLED);
331         }
332     }
333
334     private void initNegativeMappingTTL(BundleContext context) {
335         // set the default value first
336         this.negativeMappingTTL = DEFAULT_NEGATIVE_MAPPING_TTL;
337
338         String str = null;
339
340         if (context != null) {
341             str = context.getProperty(LISP_NEGATIVE_MAPPING_TTL);
342         }
343
344         if (str == null) {
345             str = System.getProperty(LISP_NEGATIVE_MAPPING_TTL);
346             if (str == null) {
347                 LOG.debug("Configuration variable '{}' is unset. Setting to default value: '{}'",
348                         LISP_NEGATIVE_MAPPING_TTL, negativeMappingTTL);
349                 return;
350             }
351         }
352
353         try {
354             this.negativeMappingTTL = Integer.parseInt(str);
355             LOG.debug("Setting configuration variable '{}' to '{}'", LISP_NEGATIVE_MAPPING_TTL, negativeMappingTTL);
356         } catch (NumberFormatException e) {
357             LOG.debug("Configuration variable '{}' was not set correctly. Negative TTL "
358                     + "is set to default value ({} minutes)", LISP_NEGATIVE_MAPPING_TTL, negativeMappingTTL);
359         }
360     }
361
362     //one bucket should contain mapping of approximate 1 min time frame
363     private void initBucketNumber() {
364         numberOfBucketsInTimeBucketWheel = (int) (TimeUnit.MILLISECONDS.toMinutes(getRegistrationValiditySb()) + 1);
365
366         numberOfBucketsInTimeBucketWheel = Math.max(numberOfBucketsInTimeBucketWheel,
367                 MIN_NUMBER_OF_BUCKETS_IN_TIME_BUCKET_WHEEL);
368     }
369
370     public boolean mappingMergeIsSet() {
371         return mappingMerge;
372     }
373
374     public void setMappingMerge(boolean mappingMerge) {
375         LOG.debug("Setting configuration variable '{}' to '{}'", LISP_MAPPING_MERGE, (mappingMerge));
376         this.mappingMerge = (mappingMerge);
377     }
378
379     public boolean smrIsSet() {
380         return smr;
381     }
382
383     public void setSmr(boolean smr) {
384         LOG.debug("Setting configuration variable '{}' to '{}'", LISP_SMR, smr);
385         this.smr = smr;
386     }
387
388     public String getElpPolicy() {
389         return elpPolicy;
390     }
391
392     public IMappingService.LookupPolicy getLookupPolicy() {
393         return lookupPolicy;
394     }
395
396     public long getRegistrationValiditySb() {
397         return registrationValiditySb;
398     }
399
400     public long getDefaultRegistrationValiditySb() {
401         return MIN_REGISTRATION_VALIDITY_SB;
402     }
403
404     public void setRegistrationValiditySb(long registrationValiditySb) {
405         this.registrationValiditySb = registrationValiditySb;
406         if (registrationValiditySb < MIN_REGISTRATION_VALIDITY_SB) {
407             LOG.warn("Registration validity is less than the default 3.33 minutes!!!");
408         }
409     }
410
411     public void setLookupPolicy(IMappingService.LookupPolicy lookupPolicy) {
412         this.lookupPolicy = lookupPolicy;
413     }
414
415     public void setSmrRetryCount(int smrRetryCount) {
416         LOG.debug("Setting configuration variable '{}' to '{}'", LISP_SMR_RETRY_COUNT, smrRetryCount);
417         this.smrRetryCount = smrRetryCount;
418     }
419
420     public int getSmrRetryCount() {
421         return smrRetryCount;
422     }
423
424     public void setSmrTimeout(long smrTimeout) {
425         LOG.debug("Setting configuration variable '{}' to '{}'", LISP_SMR_TIMEOUT, smrTimeout);
426         this.smrTimeout = smrTimeout;
427     }
428
429     public long getSmrTimeout() {
430         return this.smrTimeout;
431     }
432
433     public boolean isAuthEnabled() {
434         return this.authEnabled;
435     }
436
437     public void setAuthEnabled(boolean authEnabled) {
438         LOG.debug("Setting configuration variable '{}' to '{}'", LISP_AUTH_ENABLED, authEnabled);
439         this.authEnabled = authEnabled;
440     }
441
442     public void setNegativeMappingTTL(int negativeMappingTTL) {
443         LOG.debug("Setting configuration variable '{}' to '{}'", LISP_NEGATIVE_MAPPING_TTL, negativeMappingTTL);
444         this.negativeMappingTTL = negativeMappingTTL;
445     }
446
447     public int getNegativeMappingTTL() {
448         return this.negativeMappingTTL;
449     }
450
451     public int getNumberOfBucketsInTimeBucketWheel() {
452         return numberOfBucketsInTimeBucketWheel;
453     }
454
455     public long  getMaximumTimeoutTolerance() {
456         return TIMEOUT_TOLERANCE_MULTIPLIER_IN_TIME_BUCKET_WHEEL * getRegistrationValiditySb();
457     }
458
459     public static ConfigIni getInstance() {
460         return INSTANCE;
461     }
462 }