Merge "Resolve Bug:593. Persister should communicate via OSGi SR instead of TCP."
[controller.git] / opendaylight / netconf / config-persister-impl / src / main / java / org / opendaylight / controller / netconf / persist / impl / osgi / ConfigPersisterActivator.java
1 /*
2  * Copyright (c) 2013 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
9 package org.opendaylight.controller.netconf.persist.impl.osgi;
10
11 import com.google.common.annotations.VisibleForTesting;
12 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
13 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
14 import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
15 import org.opendaylight.controller.netconf.persist.impl.ConfigPusher;
16 import org.opendaylight.controller.netconf.persist.impl.PersisterAggregator;
17 import org.osgi.framework.BundleActivator;
18 import org.osgi.framework.BundleContext;
19 import org.osgi.framework.Constants;
20 import org.osgi.framework.Filter;
21 import org.osgi.framework.ServiceReference;
22 import org.osgi.util.tracker.ServiceTracker;
23 import org.osgi.util.tracker.ServiceTrackerCustomizer;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 import javax.management.MBeanServer;
28 import java.lang.management.ManagementFactory;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.concurrent.TimeUnit;
32
33 public class ConfigPersisterActivator implements BundleActivator {
34
35     private static final Logger logger = LoggerFactory.getLogger(ConfigPersisterActivator.class);
36
37     public static final String MAX_WAIT_FOR_CAPABILITIES_MILLIS_PROPERTY = "maxWaitForCapabilitiesMillis";
38     private static final long MAX_WAIT_FOR_CAPABILITIES_MILLIS_DEFAULT = TimeUnit.MINUTES.toMillis(2);
39     public static final String CONFLICTING_VERSION_TIMEOUT_MILLIS_PROPERTY = "conflictingVersionTimeoutMillis";
40     private static final long CONFLICTING_VERSION_TIMEOUT_MILLIS_DEFAULT = TimeUnit.SECONDS.toMillis(30);
41
42     public static final String NETCONF_CONFIG_PERSISTER = "netconf.config.persister";
43
44     public static final String STORAGE_ADAPTER_CLASS_PROP_SUFFIX = "storageAdapterClass";
45
46
47     private static final MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
48
49     private List<AutoCloseable> autoCloseables;
50
51
52     @Override
53     public void start(final BundleContext context) throws Exception {
54         logger.debug("ConfigPersister starting");
55         autoCloseables = new ArrayList<>();
56         PropertiesProviderBaseImpl propertiesProvider = new PropertiesProviderBaseImpl(context);
57
58
59         final PersisterAggregator persisterAggregator = PersisterAggregator.createFromProperties(propertiesProvider);
60         autoCloseables.add(persisterAggregator);
61         final long maxWaitForCapabilitiesMillis = getMaxWaitForCapabilitiesMillis(propertiesProvider);
62         final List<ConfigSnapshotHolder> configs = persisterAggregator.loadLastConfigs();
63         final long conflictingVersionTimeoutMillis = getConflictingVersionTimeoutMillis(propertiesProvider);
64         logger.trace("Following configs will be pushed: {}", configs);
65         ServiceTrackerCustomizer<NetconfOperationServiceFactory, NetconfOperationServiceFactory> configNetconfCustomizer = new ServiceTrackerCustomizer<NetconfOperationServiceFactory, NetconfOperationServiceFactory>() {
66             @Override
67             public NetconfOperationServiceFactory addingService(ServiceReference<NetconfOperationServiceFactory> reference) {
68                 NetconfOperationServiceFactory service = reference.getBundle().getBundleContext().getService(reference);
69                 final ConfigPusher configPusher = new ConfigPusher(service, maxWaitForCapabilitiesMillis, conflictingVersionTimeoutMillis);
70                 logger.debug("Configuration Persister got %s", service);
71                 final Thread pushingThread = new Thread(new Runnable() {
72                     @Override
73                     public void run() {
74                         configPusher.pushConfigs(configs);
75                         logger.info("Configuration Persister initialization completed.");
76                         ConfigPersisterNotificationHandler jmxNotificationHandler = new ConfigPersisterNotificationHandler(platformMBeanServer, persisterAggregator);
77                         synchronized (ConfigPersisterActivator.this) {
78                             autoCloseables.add(jmxNotificationHandler);
79                         }
80                     }
81                 }, "config-pusher");
82                 synchronized (ConfigPersisterActivator.this){
83                     autoCloseables.add(new AutoCloseable() {
84                         @Override
85                         public void close() throws Exception {
86                             pushingThread.interrupt();
87                         }
88                     });
89                 }
90                 pushingThread.start();
91                 return service;
92             }
93
94             @Override
95             public void modifiedService(ServiceReference<NetconfOperationServiceFactory> reference, NetconfOperationServiceFactory service) {
96             }
97
98             @Override
99             public void removedService(ServiceReference<NetconfOperationServiceFactory> reference, NetconfOperationServiceFactory service) {
100             }
101         };
102
103         Filter filter = context.createFilter(getFilterString());
104
105         ServiceTracker<NetconfOperationServiceFactory, NetconfOperationServiceFactory> tracker =
106                 new ServiceTracker<>(context, filter, configNetconfCustomizer);
107         tracker.open();
108     }
109
110
111     @VisibleForTesting
112     public static String getFilterString() {
113         return "(&" +
114                 "(" + Constants.OBJECTCLASS + "=" + NetconfOperationServiceFactory.class.getName() + ")" +
115                 "(name" + "=" + "config-netconf-connector" + ")" +
116                 ")";
117     }
118
119     private long getConflictingVersionTimeoutMillis(PropertiesProviderBaseImpl propertiesProvider) {
120         String timeoutProperty = propertiesProvider.getProperty(CONFLICTING_VERSION_TIMEOUT_MILLIS_PROPERTY);
121         return timeoutProperty == null ? CONFLICTING_VERSION_TIMEOUT_MILLIS_DEFAULT : Long.valueOf(timeoutProperty);
122     }
123
124     private long getMaxWaitForCapabilitiesMillis(PropertiesProviderBaseImpl propertiesProvider) {
125         String timeoutProperty = propertiesProvider.getProperty(MAX_WAIT_FOR_CAPABILITIES_MILLIS_PROPERTY);
126         return timeoutProperty == null ? MAX_WAIT_FOR_CAPABILITIES_MILLIS_DEFAULT : Long.valueOf(timeoutProperty);
127     }
128
129     @Override
130     public synchronized void stop(BundleContext context) throws Exception {
131         Exception lastException = null;
132         for (AutoCloseable autoCloseable : autoCloseables) {
133             try {
134                 autoCloseable.close();
135             } catch (Exception e) {
136                 if (lastException == null) {
137                     lastException = e;
138                 } else {
139                     lastException.addSuppressed(e);
140                 }
141             }
142         }
143         if (lastException != null) {
144             throw lastException;
145         }
146     }
147 }