2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.controller.config.yang.shutdown.impl;
10 import com.google.common.base.Optional;
11 import java.lang.management.ManagementFactory;
12 import java.lang.management.ThreadInfo;
13 import org.opendaylight.controller.config.shutdown.ShutdownService;
14 import org.osgi.framework.Bundle;
15 import org.osgi.framework.BundleException;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
19 public class ShutdownServiceImpl implements ShutdownService, AutoCloseable {
20 private final ShutdownService impl;
21 private final ShutdownRuntimeRegistration registration;
23 public ShutdownServiceImpl(final String secret, final Bundle systemBundle,
24 final ShutdownRuntimeRegistrator rootRuntimeBeanRegistratorWrapper) {
26 throw new IllegalArgumentException("Secret cannot be null");
28 impl = new Impl(secret, systemBundle);
29 registration = rootRuntimeBeanRegistratorWrapper.register(new MXBeanImpl(impl));
33 public void shutdown(final String inputSecret, final Long maxWaitTime, final Optional<String> reason) {
34 impl.shutdown(inputSecret, maxWaitTime, reason);
43 class Impl implements ShutdownService {
44 private static final Logger LOG = LoggerFactory.getLogger(Impl.class);
45 private final String secret;
46 private final Bundle systemBundle;
48 Impl(final String secret, final Bundle systemBundle) {
50 this.systemBundle = systemBundle;
54 public void shutdown(final String inputSecret, final Long maxWaitTime, final Optional<String> reason) {
55 LOG.warn("Shutdown issued with secret {} and reason {}", inputSecret, reason);
57 Thread.sleep(1000); // prevent brute force attack
58 } catch (final InterruptedException e) {
59 Thread.currentThread().interrupt();
60 LOG.warn("Shutdown process interrupted", e);
62 if (this.secret.equals(inputSecret)) {
63 LOG.info("Server is shutting down");
66 Thread stopSystemBundleThread = new StopSystemBundleThread(systemBundle);
67 stopSystemBundleThread.start();
68 if (maxWaitTime != null && maxWaitTime > 0) {
69 Thread systemExitThread = new CallSystemExitThread(maxWaitTime);
70 LOG.debug("Scheduling {}", systemExitThread);
71 systemExitThread.start();
75 LOG.warn("Unauthorized attempt to shut down server");
76 throw new IllegalArgumentException("Invalid secret");
82 class StopSystemBundleThread extends Thread {
83 private static final Logger LOG = LoggerFactory.getLogger(StopSystemBundleThread.class);
84 private final Bundle systemBundle;
86 StopSystemBundleThread(final Bundle systemBundle) {
87 super("stop-system-bundle");
88 this.systemBundle = systemBundle;
94 // wait so that JMX response is received
96 LOG.debug("Stopping system bundle");
98 } catch (final BundleException e) {
99 LOG.warn("Can not stop OSGi server", e);
100 } catch (final InterruptedException e) {
101 LOG.warn("Shutdown process interrupted", e);
106 class CallSystemExitThread extends Thread {
107 private static final Logger LOG = LoggerFactory.getLogger(CallSystemExitThread.class);
108 private final long maxWaitTime;
109 CallSystemExitThread(final long maxWaitTime) {
110 super("call-system-exit-daemon");
112 if (maxWaitTime <= 0){
113 throw new IllegalArgumentException("Cannot schedule to zero or negative time:" + maxWaitTime);
115 this.maxWaitTime = maxWaitTime;
119 public String toString() {
120 return "CallSystemExitThread{" +
121 "maxWaitTime=" + maxWaitTime +
128 // wait specified time
129 Thread.sleep(maxWaitTime);
130 LOG.error("Since some threads are still running, server is going to shut down via System.exit(1) !");
132 ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads(true, true);
133 StringBuffer sb = new StringBuffer();
134 for(ThreadInfo info : threads) {
138 LOG.warn("Thread dump:{}", sb);
140 } catch (final InterruptedException e) {
141 LOG.warn("Interrupted, not going to call System.exit(1)");
147 class MXBeanImpl implements ShutdownRuntimeMXBean {
148 private final ShutdownService impl;
150 MXBeanImpl(final ShutdownService impl) {
155 public void shutdown(final String inputSecret, final Long maxWaitTime, final String nullableReason) {
156 Optional<String> optionalReason;
157 if (nullableReason == null) {
158 optionalReason = Optional.absent();
160 optionalReason = Optional.of(nullableReason);
162 impl.shutdown(inputSecret, maxWaitTime, optionalReason);