Merge "included the nodetype in the congruence check. also handled the condition...
[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 com.google.common.base.Optional;
13 import io.netty.channel.EventLoopGroup;
14 import io.netty.channel.nio.NioEventLoopGroup;
15 import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
16 import org.opendaylight.controller.netconf.persist.impl.ConfigPusher;
17 import org.opendaylight.controller.netconf.persist.impl.ConfigPusherConfiguration;
18 import org.opendaylight.controller.netconf.persist.impl.ConfigPusherConfigurationBuilder;
19 import org.opendaylight.controller.netconf.persist.impl.PersisterAggregator;
20 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
21 import org.osgi.framework.BundleActivator;
22 import org.osgi.framework.BundleContext;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 import javax.management.MBeanServer;
27 import java.lang.management.ManagementFactory;
28 import java.net.InetSocketAddress;
29 import java.util.concurrent.ThreadFactory;
30 import java.util.regex.Pattern;
31
32 public class ConfigPersisterActivator implements BundleActivator {
33
34     private static final Logger logger = LoggerFactory.getLogger(ConfigPersisterActivator.class);
35
36     public static final String IGNORED_MISSING_CAPABILITY_REGEX_SUFFIX = "ignoredMissingCapabilityRegex";
37
38     public static final String MAX_WAIT_FOR_CAPABILITIES_MILLIS = "maxWaitForCapabilitiesMillis";
39
40     public static final String NETCONF_CONFIG_PERSISTER = "netconf.config.persister";
41
42     public static final String STORAGE_ADAPTER_CLASS_PROP_SUFFIX = "storageAdapterClass";
43
44     public static final String DEFAULT_IGNORED_REGEX = "^urn:ietf:params:xml:ns:netconf:base:1.0";
45
46     private final MBeanServer platformMBeanServer;
47
48     private final Optional<ConfigPusherConfiguration> initialConfigForPusher;
49     private volatile ConfigPersisterNotificationHandler jmxNotificationHandler;
50     private Thread initializationThread;
51     private ThreadFactory initializationThreadFactory;
52     private EventLoopGroup nettyThreadGroup;
53     private PersisterAggregator persisterAggregator;
54
55     public ConfigPersisterActivator() {
56         this(new ThreadFactory() {
57             @Override
58             public Thread newThread(Runnable initializationRunnable) {
59                 return new Thread(initializationRunnable, "ConfigPersister-registrator");
60             }
61         }, ManagementFactory.getPlatformMBeanServer(), null);
62     }
63
64     @VisibleForTesting
65     protected ConfigPersisterActivator(ThreadFactory threadFactory, MBeanServer mBeanServer,
66             ConfigPusherConfiguration initialConfigForPusher) {
67         this.initializationThreadFactory = threadFactory;
68         this.platformMBeanServer = mBeanServer;
69         this.initialConfigForPusher = Optional.fromNullable(initialConfigForPusher);
70     }
71
72     @Override
73     public void start(final BundleContext context) throws Exception {
74         logger.debug("ConfigPersister starting");
75
76         PropertiesProviderBaseImpl propertiesProvider = new PropertiesProviderBaseImpl(context);
77
78         final Pattern ignoredMissingCapabilityRegex = getIgnoredCapabilitiesProperty(propertiesProvider);
79
80         persisterAggregator = PersisterAggregator.createFromProperties(propertiesProvider);
81
82         final ConfigPusher configPusher = new ConfigPusher(getConfigurationForPusher(context, propertiesProvider));
83
84         // offload initialization to another thread in order to stop blocking activator
85         Runnable initializationRunnable = new Runnable() {
86             @Override
87             public void run() {
88                 try {
89                     configPusher.pushConfigs(persisterAggregator.loadLastConfigs());
90                     jmxNotificationHandler = new ConfigPersisterNotificationHandler(platformMBeanServer, persisterAggregator,
91                             ignoredMissingCapabilityRegex);
92                 } catch (InterruptedException e) {
93                     Thread.currentThread().interrupt();
94                     logger.error("Interrupted while waiting for netconf connection");
95                     // uncaught exception handler will deal with this failure
96                     throw new RuntimeException("Interrupted while waiting for netconf connection", e);
97                 }
98                 logger.info("Configuration Persister initialization completed.");
99             }
100         };
101
102         initializationThread = initializationThreadFactory.newThread(initializationRunnable);
103         initializationThread.start();
104     }
105
106     private Pattern getIgnoredCapabilitiesProperty(PropertiesProviderBaseImpl propertiesProvider) {
107         String regexProperty = propertiesProvider.getProperty(IGNORED_MISSING_CAPABILITY_REGEX_SUFFIX);
108         String regex;
109         if (regexProperty != null) {
110             regex = regexProperty;
111         } else {
112             regex = DEFAULT_IGNORED_REGEX;
113         }
114         return Pattern.compile(regex);
115     }
116
117     private Optional<Long> getMaxWaitForCapabilitiesProperty(PropertiesProviderBaseImpl propertiesProvider) {
118         String timeoutProperty = propertiesProvider.getProperty(MAX_WAIT_FOR_CAPABILITIES_MILLIS);
119         return Optional.fromNullable(timeoutProperty == null ? null : Long.valueOf(timeoutProperty));
120     }
121
122     private ConfigPusherConfiguration getConfigurationForPusher(BundleContext context,
123             PropertiesProviderBaseImpl propertiesProvider) {
124
125         // If configuration was injected via constructor, use it
126         if(initialConfigForPusher.isPresent())
127             return initialConfigForPusher.get();
128
129         Optional<Long> maxWaitForCapabilitiesMillis = getMaxWaitForCapabilitiesProperty(propertiesProvider);
130         final InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context,
131                 "Netconf is not configured, persister is not operational", true);
132
133         nettyThreadGroup = new NioEventLoopGroup();
134
135         ConfigPusherConfigurationBuilder configPusherConfigurationBuilder = ConfigPusherConfigurationBuilder.aConfigPusherConfiguration();
136
137         if(maxWaitForCapabilitiesMillis.isPresent())
138             configPusherConfigurationBuilder.withNetconfCapabilitiesWaitTimeoutMs(maxWaitForCapabilitiesMillis.get());
139
140         return configPusherConfigurationBuilder
141                 .withEventLoopGroup(nettyThreadGroup)
142                 .withNetconfAddress(address)
143                 .build();
144     }
145
146     @Override
147     public void stop(BundleContext context) throws Exception {
148         initializationThread.interrupt();
149         if (jmxNotificationHandler != null) {
150             jmxNotificationHandler.close();
151         }
152         if(nettyThreadGroup!=null)
153             nettyThreadGroup.shutdownGracefully();
154         persisterAggregator.close();
155     }
156 }