001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.boot;
031:
032: import com.caucho.config.Config;
033: import com.caucho.config.ConfigException;
034: import com.caucho.config.program.ConfigProgram;
035: import com.caucho.config.program.ContainerProgram;
036: import com.caucho.config.types.RawString;
037: import com.caucho.lifecycle.Lifecycle;
038: import com.caucho.loader.*;
039: import com.caucho.log.EnvironmentStream;
040: import com.caucho.log.LogConfig;
041: import com.caucho.log.RotateStream;
042: import com.caucho.server.cluster.Cluster;
043: import com.caucho.server.cluster.ClusterServer;
044: import com.caucho.server.cluster.Server;
045: import com.caucho.server.dispatch.ServletMapping;
046: import com.caucho.server.resin.ResinELContext;
047: import com.caucho.server.host.Host;
048: import com.caucho.server.host.HostConfig;
049: import com.caucho.server.port.ProtocolDispatchServer;
050: import com.caucho.server.webapp.WebApp;
051: import com.caucho.server.webapp.WebAppConfig;
052: import com.caucho.util.*;
053: import com.caucho.vfs.Path;
054: import com.caucho.vfs.Vfs;
055: import com.caucho.vfs.WriteStream;
056: import com.caucho.webbeans.manager.*;
057:
058: import java.io.*;
059: import java.util.ArrayList;
060: import java.util.Collections;
061: import java.util.HashMap;
062: import java.util.logging.Level;
063: import java.util.logging.Logger;
064: import javax.annotation.PostConstruct;
065:
066: /**
067: * Process responsible for watching a backend watchdog.
068: */
069: public class WatchdogManager extends ProtocolDispatchServer {
070: private static L10N _L;
071: private static Logger _log;
072:
073: private static WatchdogManager _watchdog;
074:
075: private WatchdogArgs _args;
076:
077: private Lifecycle _lifecycle = new Lifecycle();
078:
079: private int _watchdogPort;
080:
081: private String _adminCookie;
082: private ManagementConfig _management;
083:
084: private Server _dispatchServer;
085:
086: private boolean _isWatchdogManagerConfig;
087:
088: private HashMap<String, Watchdog> _watchdogMap = new HashMap<String, Watchdog>();
089:
090: WatchdogManager(String[] argv) throws Exception {
091: _watchdog = this ;
092:
093: _args = new WatchdogArgs(argv);
094:
095: Vfs.setPwd(_args.getRootDirectory());
096:
097: Path logPath = getLogDirectory().lookup("watchdog-manager.log");
098:
099: RotateStream stream = RotateStream.create(logPath);
100: stream.init();
101: WriteStream out = stream.getStream();
102: out.setDisableClose(true);
103:
104: EnvironmentStream.setStdout(out);
105: EnvironmentStream.setStderr(out);
106:
107: LogConfig log = new LogConfig();
108: log.setName("");
109: log.setPath(logPath);
110: log.init();
111:
112: ThreadPool.getThreadPool().setThreadIdleMin(1);
113: ThreadPool.getThreadPool().setThreadIdleMax(5);
114:
115: ResinELContext elContext = _args.getELContext();
116:
117: WebBeansContainer webBeans = WebBeansContainer.create();
118: webBeans.addSingletonByName(elContext.getResinHome(),
119: "resinHome");
120: webBeans.addSingletonByName(elContext.getJavaVar(), "java");
121: webBeans.addSingletonByName(elContext.getResinVar(), "resin");
122: webBeans.addSingletonByName(elContext.getServerVar(), "server");
123:
124: _watchdogPort = _args.getWatchdogPort();
125: readConfig(_args);
126:
127: Watchdog server = _watchdogMap.get(_args.getServerId());
128:
129: if (server == null)
130: throw new IllegalStateException(L().l(
131: "'{0}' is an unknown server", _args.getServerId()));
132:
133: Cluster cluster = new Cluster();
134: ClusterServer clusterServer = new ClusterServer(cluster);
135:
136: if (_watchdogPort > 0)
137: clusterServer.setPort(_watchdogPort);
138: else
139: clusterServer.setPort(server.getWatchdogPort());
140:
141: clusterServer.getClusterPort().setMinSpareListen(1);
142: clusterServer.getClusterPort().setMaxSpareListen(2);
143:
144: _dispatchServer = new Server(clusterServer);
145:
146: HostConfig hostConfig = new HostConfig();
147: hostConfig.setId("resin-admin");
148:
149: hostConfig.init();
150:
151: _dispatchServer.addHost(hostConfig);
152: _dispatchServer.init();
153: _dispatchServer.start();
154:
155: Host host = _dispatchServer.getHost("resin-admin", 0);
156:
157: WebAppConfig webAppConfig = new WebAppConfig();
158: webAppConfig.setId("");
159: webAppConfig
160: .setRootDirectory(new RawString("watchdog-manager"));
161:
162: host.addWebApp(webAppConfig);
163:
164: WebApp webApp = host.findWebAppByURI("/");
165:
166: ServletMapping servlet = webApp.createServletMapping();
167:
168: servlet.setServletName("watchdog");
169: servlet.addURLPattern("/watchdog");
170: servlet.setServletClass("com.caucho.boot.WatchdogServlet");
171: servlet.init();
172:
173: webApp.addServletMapping(servlet);
174: try {
175: host.updateWebAppDeploy("/");
176: } catch (Throwable e) {
177: log().log(Level.WARNING, e.toString(), e);
178: }
179:
180: webApp.start();
181: }
182:
183: static WatchdogManager getWatchdog() {
184: return _watchdog;
185: }
186:
187: public void setAdminCookie(String cookie) {
188: if (_adminCookie == null)
189: _adminCookie = cookie;
190: }
191:
192: public String getAdminCookie() {
193: if (_adminCookie != null)
194: return _adminCookie;
195: else if (_management != null)
196: return _management.getAdminCookie();
197: else
198: return null;
199: }
200:
201: Path getRootDirectory() {
202: return _args.getRootDirectory();
203: }
204:
205: Path getLogDirectory() {
206: Path logDirectory = _args.getLogDirectory();
207:
208: if (logDirectory != null)
209: return logDirectory;
210: else
211: return getRootDirectory().lookup("log");
212: }
213:
214: boolean authenticate(String password) {
215: String cookie = getAdminCookie();
216:
217: if (password == null && cookie == null)
218: return true;
219: else if (password != null && password.equals(getAdminCookie()))
220: return true;
221: else
222: return false;
223: }
224:
225: Watchdog findServer(String id) {
226: return _watchdogMap.get(id);
227: }
228:
229: String status() {
230: StringBuilder sb = new StringBuilder();
231:
232: ArrayList<String> keys = new ArrayList<String>(_watchdogMap
233: .keySet());
234: Collections.sort(keys);
235:
236: for (String key : keys) {
237: Watchdog watchdog = _watchdogMap.get(key);
238:
239: sb.append("\n");
240: sb.append("server '" + key + "' : " + watchdog.getState()
241: + "\n");
242:
243: if (getAdminCookie() == null)
244: sb.append(" password: missing\n");
245: else
246: sb.append(" password: ok\n");
247:
248: sb.append(" user: " + System.getProperty("user.name"));
249:
250: if (watchdog.getGroupName() != null)
251: sb.append("(" + watchdog.getGroupName() + ")");
252:
253: sb.append("\n");
254:
255: sb.append(" root: " + watchdog.getResinRoot() + "\n");
256: sb.append(" conf: " + watchdog.getResinConf() + "\n");
257: }
258:
259: return sb.toString();
260: }
261:
262: void startServer(String[] argv) throws ConfigException {
263: WatchdogArgs args = new WatchdogArgs(argv);
264:
265: String serverId = args.getServerId();
266:
267: Vfs.setPwd(_args.getRootDirectory());
268:
269: try {
270: readConfig(args);
271: } catch (Exception e) {
272: throw ConfigException.create(e);
273: }
274:
275: Watchdog watchdog = _watchdogMap.get(serverId);
276:
277: if (watchdog == null)
278: throw new ConfigException(
279: L()
280: .l(
281: "No matching <server> found for -server '{0}' in '{1}'",
282: serverId, _args.getResinConf()));
283:
284: watchdog.start();
285: }
286:
287: void stopServer(String serverId) {
288: Watchdog watchdog = _watchdogMap.get(serverId);
289:
290: if (watchdog == null)
291: throw new ConfigException(
292: L()
293: .l(
294: "No matching <server> found for -server '{0}' in {1}",
295: serverId, _args.getResinConf()));
296:
297: watchdog.stop();
298: }
299:
300: void killServer(String serverId) {
301: Watchdog watchdog = _watchdogMap.get(serverId);
302:
303: if (watchdog == null)
304: throw new ConfigException(
305: L()
306: .l(
307: "No matching <server> found for -server '{0}' in {1}",
308: serverId, _args.getResinConf()));
309:
310: watchdog.kill();
311: }
312:
313: void restartServer(String serverId, String[] argv) {
314: Watchdog server = _watchdogMap.get(serverId);
315:
316: if (server != null)
317: server.stop();
318:
319: startServer(argv);
320: }
321:
322: private void readConfig(WatchdogArgs args) throws Exception {
323: Config config = new Config();
324: // ignore since we don't want to start databases
325: config.setIgnoreEnvironment(true);
326:
327: Vfs.setPwd(args.getRootDirectory());
328: ResinConfig resin = new ResinConfig(args);
329:
330: config.configure(resin, args.getResinConf(),
331: "com/caucho/server/resin/resin.rnc");
332: }
333:
334: public static void main(String[] argv) throws Exception {
335: WatchdogManager manager = new WatchdogManager(argv);
336: manager.startServer(argv);
337: }
338:
339: private static L10N L() {
340: if (_L == null)
341: _L = new L10N(ResinBoot.class);
342:
343: return _L;
344: }
345:
346: private static Logger log() {
347: if (_log == null)
348: _log = Logger.getLogger(ResinBoot.class.getName());
349:
350: return _log;
351: }
352:
353: //
354: // configuration classes
355: //
356:
357: /**
358: * Class for the initial WatchdogManager configuration.
359: */
360: class ResinConfig {
361: private WatchdogArgs _args;
362:
363: private ArrayList<ContainerProgram> _clusterDefaultList = new ArrayList<ContainerProgram>();
364:
365: ResinConfig() {
366: _args = WatchdogManager.this ._args;
367: }
368:
369: ResinConfig(WatchdogArgs args) {
370: _args = args;
371: }
372:
373: public WatchdogArgs getArgs() {
374: return _args;
375: }
376:
377: public String getId() {
378: if (_args == null)
379: return "default";
380: else
381: return _args.getServerId();
382: }
383:
384: public void setManagement(ManagementConfig management) {
385: if (_management == null)
386: _management = management;
387: }
388:
389: public void addClusterDefault(ContainerProgram program) {
390: _clusterDefaultList.add(program);
391: }
392:
393: public WatchdogManagerConfig createWatchdogManager() {
394: _isWatchdogManagerConfig = true;
395:
396: return new WatchdogManagerConfig(this );
397: }
398:
399: public ClusterConfig createCluster() {
400: ClusterConfig cluster = new ClusterConfig(this );
401:
402: for (int i = 0; i < _clusterDefaultList.size(); i++)
403: _clusterDefaultList.get(i).configure(cluster);
404:
405: return cluster;
406: }
407:
408: public ServerCompatConfig createServer() {
409: return new ServerCompatConfig();
410: }
411:
412: /**
413: * Ignore items we can't understand.
414: */
415: public void addBuilderProgram(ConfigProgram program) {
416: }
417: }
418:
419: public class WatchdogManagerConfig {
420: private ResinConfig _resin;
421:
422: private ArrayList<ContainerProgram> _watchdogDefaultList = new ArrayList<ContainerProgram>();
423:
424: WatchdogManagerConfig(ResinConfig resin) {
425: _resin = resin;
426: }
427:
428: public void setWatchdogPort(int port) {
429: if (_args.getWatchdogPort() == 0)
430: _args.setWatchdogPort(port);
431: }
432:
433: public void addWatchdogDefault(ContainerProgram program) {
434: _watchdogDefaultList.add(program);
435: }
436:
437: public WatchdogConfig createWatchdog() {
438: WatchdogConfig config = new WatchdogConfig(_resin.getArgs());
439:
440: for (int i = 0; i < _watchdogDefaultList.size(); i++)
441: _watchdogDefaultList.get(i).configure(config);
442:
443: return config;
444: }
445:
446: public void addWatchdog(WatchdogConfig config)
447: throws ConfigException {
448: Watchdog watchdog = _watchdogMap.get(config.getId());
449:
450: if (watchdog == null)
451: _watchdogMap.put(config.getId(), new Watchdog(config));
452: else if (_resin.getId().equals(watchdog.getId()))
453: watchdog.setConfig(config);
454:
455: /*
456: throw new ConfigException(L().l("<server id='{0}'> is a duplicate server. servers must have unique ids.",
457: config.getId()));
458: */
459: }
460: }
461:
462: public class ClusterConfig {
463: private ResinConfig _resin;
464:
465: private ArrayList<ContainerProgram> _serverDefaultList = new ArrayList<ContainerProgram>();
466:
467: ClusterConfig(ResinConfig resin) {
468: _resin = resin;
469: }
470:
471: /**
472: * Adds a new server to the cluster.
473: */
474: public void addServerDefault(ContainerProgram program) {
475: _serverDefaultList.add(program);
476: }
477:
478: public void addManagement(ManagementConfig management) {
479: if (_management == null)
480: _management = management;
481: }
482:
483: public WatchdogConfig createServer() {
484: WatchdogConfig config = new WatchdogConfig(_resin.getArgs());
485:
486: for (int i = 0; i < _serverDefaultList.size(); i++)
487: _serverDefaultList.get(i).configure(config);
488:
489: return config;
490: }
491:
492: public void addServer(WatchdogConfig config)
493: throws ConfigException {
494: if (_isWatchdogManagerConfig)
495: return;
496:
497: Watchdog watchdog = _watchdogMap.get(config.getId());
498:
499: if (watchdog == null)
500: _watchdogMap.put(config.getId(), new Watchdog(config));
501: else if (watchdog.getResinConf().equals(
502: config.getResinConf())) {
503: if (_resin.getId().equals(config.getId()))
504: watchdog.setConfig(config);
505: } else
506: throw new ConfigException(
507: L()
508: .l(
509: "<server id='{0}'> is a duplicate server. servers must have unique ids.",
510: config.getId()));
511: }
512:
513: /**
514: * Ignore items we can't understand.
515: */
516: public void addBuilderProgram(ConfigProgram program) {
517: }
518: }
519:
520: public class ServerCompatConfig {
521: public ClusterCompatConfig createCluster() {
522: return new ClusterCompatConfig();
523: }
524:
525: public SrunCompatConfig createHttp() {
526: return new SrunCompatConfig();
527: }
528:
529: /**
530: * Ignore items we can't understand.
531: */
532: public void addBuilderProgram(ConfigProgram program) {
533: }
534: }
535:
536: public class ClusterCompatConfig {
537: public SrunCompatConfig createSrun() {
538: return new SrunCompatConfig();
539: }
540:
541: /**
542: * Ignore items we can't understand.
543: */
544: public void addBuilderProgram(ConfigProgram program) {
545: }
546: }
547:
548: public class SrunCompatConfig {
549: private String _id = "";
550:
551: public void setId(String id) {
552: _id = id;
553: }
554:
555: public void setServerId(String id) {
556: _id = id;
557: }
558:
559: /**
560: * Ignore items we can't understand.
561: */
562: public void addBuilderProgram(ConfigProgram program) {
563: }
564:
565: @PostConstruct
566: public void init() {
567: if (_isWatchdogManagerConfig)
568: return;
569:
570: Watchdog server = findServer(_id);
571:
572: if (server != null)
573: return;
574:
575: server = new Watchdog(_id, _args);
576:
577: _watchdogMap.put(_id, server);
578: }
579: }
580: }
|