X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fnetconf%2Fconfig-persister-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Fpersist%2Fimpl%2Fosgi%2FConfigPersisterActivator.java;h=0cc55719e12875ece51220073657867fc3a9c21f;hp=1246c78fbe21539589a23d641e58f4a1846da5c8;hb=f776809962df87deeaa533ba995cc6fceba64d0e;hpb=5b16b5aa030d26cbf2c6dc17b3f7a530fbdb987f diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java index 1246c78fbe..0cc55719e1 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterActivator.java @@ -9,148 +9,176 @@ package org.opendaylight.controller.netconf.persist.impl.osgi; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Optional; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; +import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler; import org.opendaylight.controller.netconf.persist.impl.ConfigPusher; -import org.opendaylight.controller.netconf.persist.impl.ConfigPusherConfiguration; -import org.opendaylight.controller.netconf.persist.impl.ConfigPusherConfigurationBuilder; import org.opendaylight.controller.netconf.persist.impl.PersisterAggregator; -import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil; +import org.opendaylight.controller.netconf.util.CloseableUtil; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.Filter; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.management.MBeanServer; import java.lang.management.ManagementFactory; -import java.net.InetSocketAddress; -import java.util.concurrent.ThreadFactory; -import java.util.regex.Pattern; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; public class ConfigPersisterActivator implements BundleActivator { private static final Logger logger = LoggerFactory.getLogger(ConfigPersisterActivator.class); + private static final MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer(); - public static final String IGNORED_MISSING_CAPABILITY_REGEX_SUFFIX = "ignoredMissingCapabilityRegex"; - - public static final String MAX_WAIT_FOR_CAPABILITIES_MILLIS = "maxWaitForCapabilitiesMillis"; + public static final String MAX_WAIT_FOR_CAPABILITIES_MILLIS_PROPERTY = "maxWaitForCapabilitiesMillis"; + private static final long MAX_WAIT_FOR_CAPABILITIES_MILLIS_DEFAULT = TimeUnit.MINUTES.toMillis(2); + public static final String CONFLICTING_VERSION_TIMEOUT_MILLIS_PROPERTY = "conflictingVersionTimeoutMillis"; + private static final long CONFLICTING_VERSION_TIMEOUT_MILLIS_DEFAULT = TimeUnit.SECONDS.toMillis(30); public static final String NETCONF_CONFIG_PERSISTER = "netconf.config.persister"; public static final String STORAGE_ADAPTER_CLASS_PROP_SUFFIX = "storageAdapterClass"; - public static final String DEFAULT_IGNORED_REGEX = "^urn:ietf:params:xml:ns:netconf:base:1.0"; - - private final MBeanServer platformMBeanServer; - - private final Optional initialConfigForPusher; - private volatile ConfigPersisterNotificationHandler jmxNotificationHandler; - private Thread initializationThread; - private ThreadFactory initializationThreadFactory; - private EventLoopGroup nettyThreadGroup; - private PersisterAggregator persisterAggregator; + private List autoCloseables; - public ConfigPersisterActivator() { - this(new ThreadFactory() { - @Override - public Thread newThread(Runnable initializationRunnable) { - return new Thread(initializationRunnable, "ConfigPersister-registrator"); - } - }, ManagementFactory.getPlatformMBeanServer(), null); - } - - @VisibleForTesting - protected ConfigPersisterActivator(ThreadFactory threadFactory, MBeanServer mBeanServer, - ConfigPusherConfiguration initialConfigForPusher) { - this.initializationThreadFactory = threadFactory; - this.platformMBeanServer = mBeanServer; - this.initialConfigForPusher = Optional.fromNullable(initialConfigForPusher); - } @Override public void start(final BundleContext context) throws Exception { logger.debug("ConfigPersister starting"); - + autoCloseables = new ArrayList<>(); PropertiesProviderBaseImpl propertiesProvider = new PropertiesProviderBaseImpl(context); - final Pattern ignoredMissingCapabilityRegex = getIgnoredCapabilitiesProperty(propertiesProvider); - - persisterAggregator = PersisterAggregator.createFromProperties(propertiesProvider); - - final ConfigPusher configPusher = new ConfigPusher(getConfigurationForPusher(context, propertiesProvider)); - - // offload initialization to another thread in order to stop blocking activator - Runnable initializationRunnable = new Runnable() { - @Override - public void run() { - try { - configPusher.pushConfigs(persisterAggregator.loadLastConfigs()); - jmxNotificationHandler = new ConfigPersisterNotificationHandler(platformMBeanServer, persisterAggregator, - ignoredMissingCapabilityRegex); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - logger.error("Interrupted while waiting for netconf connection"); - // uncaught exception handler will deal with this failure - throw new RuntimeException("Interrupted while waiting for netconf connection", e); - } - logger.info("Configuration Persister initialization completed."); - } - }; + final PersisterAggregator persisterAggregator = PersisterAggregator.createFromProperties(propertiesProvider); + autoCloseables.add(persisterAggregator); + long maxWaitForCapabilitiesMillis = getMaxWaitForCapabilitiesMillis(propertiesProvider); + List configs = persisterAggregator.loadLastConfigs(); + long conflictingVersionTimeoutMillis = getConflictingVersionTimeoutMillis(propertiesProvider); + logger.trace("Following configs will be pushed: {}", configs); + + InnerCustomizer innerCustomizer = new InnerCustomizer(configs, maxWaitForCapabilitiesMillis, + conflictingVersionTimeoutMillis, persisterAggregator); + OuterCustomizer outerCustomizer = new OuterCustomizer(context, innerCustomizer); + new ServiceTracker<>(context, NetconfOperationProvider.class, outerCustomizer).open(); + } - initializationThread = initializationThreadFactory.newThread(initializationRunnable); - initializationThread.start(); + private long getConflictingVersionTimeoutMillis(PropertiesProviderBaseImpl propertiesProvider) { + String timeoutProperty = propertiesProvider.getProperty(CONFLICTING_VERSION_TIMEOUT_MILLIS_PROPERTY); + return timeoutProperty == null ? CONFLICTING_VERSION_TIMEOUT_MILLIS_DEFAULT : Long.valueOf(timeoutProperty); } - private Pattern getIgnoredCapabilitiesProperty(PropertiesProviderBaseImpl propertiesProvider) { - String regexProperty = propertiesProvider.getProperty(IGNORED_MISSING_CAPABILITY_REGEX_SUFFIX); - String regex; - if (regexProperty != null) { - regex = regexProperty; - } else { - regex = DEFAULT_IGNORED_REGEX; - } - return Pattern.compile(regex); + private long getMaxWaitForCapabilitiesMillis(PropertiesProviderBaseImpl propertiesProvider) { + String timeoutProperty = propertiesProvider.getProperty(MAX_WAIT_FOR_CAPABILITIES_MILLIS_PROPERTY); + return timeoutProperty == null ? MAX_WAIT_FOR_CAPABILITIES_MILLIS_DEFAULT : Long.valueOf(timeoutProperty); } - private Optional getMaxWaitForCapabilitiesProperty(PropertiesProviderBaseImpl propertiesProvider) { - String timeoutProperty = propertiesProvider.getProperty(MAX_WAIT_FOR_CAPABILITIES_MILLIS); - return Optional.fromNullable(timeoutProperty == null ? null : Long.valueOf(timeoutProperty)); + @Override + public synchronized void stop(BundleContext context) throws Exception { + CloseableUtil.closeAll(autoCloseables); + } + + + @VisibleForTesting + public static String getFilterString() { + return "(&" + + "(" + Constants.OBJECTCLASS + "=" + NetconfOperationServiceFactory.class.getName() + ")" + + "(name" + "=" + "config-netconf-connector" + ")" + + ")"; } - private ConfigPusherConfiguration getConfigurationForPusher(BundleContext context, - PropertiesProviderBaseImpl propertiesProvider) { + class OuterCustomizer implements ServiceTrackerCustomizer { + private final BundleContext context; + private final InnerCustomizer innerCustomizer; - // If configuration was injected via constructor, use it - if(initialConfigForPusher.isPresent()) - return initialConfigForPusher.get(); + OuterCustomizer(BundleContext context, InnerCustomizer innerCustomizer) { + this.context = context; + this.innerCustomizer = innerCustomizer; + } - Optional maxWaitForCapabilitiesMillis = getMaxWaitForCapabilitiesProperty(propertiesProvider); - final InetSocketAddress address = NetconfConfigUtil.extractTCPNetconfAddress(context, - "Netconf is not configured, persister is not operational", true); + @Override + public NetconfOperationProvider addingService(ServiceReference reference) { + logger.trace("Got OuterCustomizer.addingService {}", reference); + // JMX was registered, track config-netconf-connector + Filter filter; + try { + filter = context.createFilter(getFilterString()); + } catch (InvalidSyntaxException e) { + throw new IllegalStateException(e); + } + new ServiceTracker<>(context, filter, innerCustomizer).open(); + return null; + } - nettyThreadGroup = new NioEventLoopGroup(); + @Override + public void modifiedService(ServiceReference reference, NetconfOperationProvider service) { - ConfigPusherConfigurationBuilder configPusherConfigurationBuilder = ConfigPusherConfigurationBuilder.aConfigPusherConfiguration(); + } - if(maxWaitForCapabilitiesMillis.isPresent()) - configPusherConfigurationBuilder.withNetconfCapabilitiesWaitTimeoutMs(maxWaitForCapabilitiesMillis.get()); + @Override + public void removedService(ServiceReference reference, NetconfOperationProvider service) { - return configPusherConfigurationBuilder - .withEventLoopGroup(nettyThreadGroup) - .withNetconfAddress(address) - .build(); + } } - @Override - public void stop(BundleContext context) throws Exception { - initializationThread.interrupt(); - if (jmxNotificationHandler != null) { - jmxNotificationHandler.close(); + class InnerCustomizer implements ServiceTrackerCustomizer { + private final List configs; + private final PersisterAggregator persisterAggregator; + private final long maxWaitForCapabilitiesMillis, conflictingVersionTimeoutMillis; + + + InnerCustomizer(List configs, long maxWaitForCapabilitiesMillis, long conflictingVersionTimeoutMillis, + PersisterAggregator persisterAggregator) { + this.configs = configs; + this.maxWaitForCapabilitiesMillis = maxWaitForCapabilitiesMillis; + this.conflictingVersionTimeoutMillis = conflictingVersionTimeoutMillis; + this.persisterAggregator = persisterAggregator; + } + + @Override + public NetconfOperationServiceFactory addingService(ServiceReference reference) { + logger.trace("Got InnerCustomizer.addingService {}", reference); + NetconfOperationServiceFactory service = reference.getBundle().getBundleContext().getService(reference); + + final ConfigPusher configPusher = new ConfigPusher(service, maxWaitForCapabilitiesMillis, conflictingVersionTimeoutMillis); + logger.debug("Configuration Persister got {}", service); + final Thread pushingThread = new Thread(new Runnable() { + @Override + public void run() { + configPusher.pushConfigs(configs); + logger.info("Configuration Persister initialization completed."); + ConfigPersisterNotificationHandler jmxNotificationHandler = new ConfigPersisterNotificationHandler(platformMBeanServer, persisterAggregator); + synchronized (ConfigPersisterActivator.this) { + autoCloseables.add(jmxNotificationHandler); + } + } + }, "config-pusher"); + synchronized (ConfigPersisterActivator.this) { + autoCloseables.add(new AutoCloseable() { + @Override + public void close() throws Exception { + pushingThread.interrupt(); + } + }); + } + pushingThread.start(); + return service; + } + + @Override + public void modifiedService(ServiceReference reference, NetconfOperationServiceFactory service) { } - if(nettyThreadGroup!=null) - nettyThreadGroup.shutdownGracefully(); - persisterAggregator.close(); + + @Override + public void removedService(ServiceReference reference, NetconfOperationServiceFactory service) { + } + } } +