ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/conient/uk/org/iscream/cms/conient/HostDisplayPanel.java
Revision: 1.45
Committed: Fri Jan 31 17:05:50 2003 UTC (21 years, 3 months ago) by tdb
Branch: MAIN
Changes since 1.44: +4 -4 lines
Log Message:
The images (from the resources directory) are now inside the JAR file.
Thanks Pete for pointing out how to do this ;)

File Contents

# Content
1 /*
2 * i-scream central monitoring system
3 * http://www.i-scream.org.uk
4 * Copyright (C) 2000-2002 i-scream
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 //---PACKAGE DECLARATION---
22 package uk.org.iscream.cms.conient;
23
24 //---IMPORTS---
25 import uk.org.iscream.cms.server.util.*;
26 import uk.org.iscream.cms.conient.datacomponents.*;
27 import java.util.HashMap;
28 import java.util.Set;
29 import java.util.Collections;
30 import java.util.Iterator;
31 import javax.swing.BoxLayout;
32 import javax.swing.JPanel;
33 import javax.swing.JProgressBar;
34 import javax.swing.JButton;
35 import javax.swing.JLabel;
36 import javax.swing.JFrame;
37 import javax.swing.Box;
38 import java.awt.event.*;
39 import java.awt.*;
40 import javax.swing.SwingUtilities;
41 import javax.swing.ImageIcon;
42
43 /**
44 * A HostDisplayPanel is simply a JPanel containing
45 * DataComponents which relate to various host
46 * attributes. Once created, it can be asked to
47 * update the data it displays by passing it an XML
48 * packet for the host it displaying for.
49 * This then updates all the DataComponents with the
50 * values in the packet.
51 *
52 * @author $Author: tdb $
53 * @version $Id: HostDisplayPanel.java,v 1.44 2002/06/10 12:06:08 tdb Exp $
54 */
55 public class HostDisplayPanel extends JPanel {
56
57 //---FINAL ATTRIBUTES---
58
59 /**
60 * The current CVS revision of this class
61 */
62 public final String REVISION = "$Revision: 1.44 $";
63
64 //---STATIC METHODS---
65
66 //---CONSTRUCTORS---
67
68 /**
69 * Creates a new Host Display Panel and adds
70 * all the appropriate DataComponents
71 */
72 public HostDisplayPanel(String hostName) {
73 super();
74
75 // set up the Panel
76 setLayout(new BorderLayout());
77 _hostName = hostName;
78
79 // check to config to see if we want extra data or not
80 if(Configuration.getInstance().getProperty("displayExtraData").equals("1")) {
81 _extraData = true;
82 }
83
84 GridBagLayout gridbag = new GridBagLayout();
85 GridBagConstraints c = new GridBagConstraints();
86 c.fill = GridBagConstraints.HORIZONTAL;
87 c.anchor = GridBagConstraints.NORTH;
88 c.weighty = 1.0;
89 _center.setLayout(gridbag);
90
91 JPanel centerHolder = new JPanel();
92 centerHolder.add(_center);
93 add(centerHolder, "Center");
94 add(_north, "North");
95
96 addDataComponent(new StringDataComponent("Packet Type", "packet.attributes.type"));
97
98 final StringDataComponent machineName = new StringDataComponent("Host Name", "packet.attributes.machine_name");
99 addDataComponent(machineName );
100 final StringDataComponent ip = new StringDataComponent("IP Address", "packet.attributes.ip");
101 addDataComponent(ip);
102 final UptimeDataComponent uptime = new UptimeDataComponent("Uptime", "packet.os.uptime");
103 addDataComponent(uptime);
104 final StringDataComponent seq_no = new StringDataComponent("Packets since host started", "packet.attributes.seq_no");
105 addDataComponent(seq_no);
106
107 final StringDataComponent osName = new StringDataComponent("Operating System", "packet.os.name");
108 addDataComponent(osName );
109 final StringDataComponent osVer = new StringDataComponent("Operating System Version", "packet.os.version");
110 addDataComponent(osVer);
111 final StringDataComponent osRelease = new StringDataComponent("Operating System Release", "packet.os.release");
112 addDataComponent(osRelease);
113 final StringDataComponent osSysName = new StringDataComponent("System Name", "packet.os.sysname");
114 addDataComponent(osSysName );
115 final StringDataComponent netbiosName = new StringDataComponent("NetBIOS Name", "packet.os.netbios_name");
116 addDataComponent(netbiosName );
117 final StringDataComponent osPlatform = new StringDataComponent("System Architecture", "packet.os.platform");
118 addDataComponent(osPlatform );
119
120 JButton info = new JButton("Platform Information");
121 info.addActionListener(new ActionListener() {
122 public void actionPerformed(ActionEvent e) {
123 final JFrame infoFrame = new JFrame("Host platform information for - " + _hostName);
124 Box content = Box.createVerticalBox();
125 content.add(machineName);
126 content.add(ip);
127 content.add(uptime);
128 content.add(seq_no);
129 content.add(osName);
130 content.add(osVer);
131 content.add(osRelease);
132 content.add(osSysName);
133 content.add(netbiosName);
134 content.add(osPlatform);
135 infoFrame.getContentPane().add(content, "Center");
136 JButton close = new JButton("Close Window");
137 close.addActionListener(new ActionListener() {
138 public void actionPerformed(ActionEvent e) {
139 infoFrame.dispose();
140 }
141 });
142 infoFrame.getContentPane().add(close, "South");
143 infoFrame.setIconImage((new ImageIcon(getClass().getResource("/resources/server.gif"))).getImage());
144 infoFrame.pack();
145 infoFrame.setVisible(true);
146 }
147 });
148 try {
149 _heartbeatTimer = new PacketTimer("Next Heartbeat", Integer.parseInt(Configuration.getInstance().getServerProperty("Host." + hostName, "Host.TCPUpdateTime")));
150 _dataTimer = new PacketTimer("Next Data", Integer.parseInt(Configuration.getInstance().getServerProperty("Host." + hostName, "Host.UDPUpdateTime")));
151 } catch (NumberFormatException e) {
152 throw new NumberFormatException("unable to obtain a valid value for Host.UDP/TCPUpdateTime");
153 }
154 _north.setLayout(new GridLayout(2,1));
155 JPanel top1 = new JPanel(new GridLayout(1,1));
156 top1.add(new JLabel("Showing data from - " + hostName, JLabel.CENTER));
157 _north.add(top1);
158 JPanel top2 = new JPanel(new GridLayout(1,3));
159 top2.add(_dataTimer);
160 top2.add(info);
161 top2.add(_heartbeatTimer);
162 _north.add(top2);
163
164
165 JPanel date = new JPanel();
166 addVisibleDataComponent(date, new DateDataComponent("Host Time", "packet.attributes.date"));
167 c.gridy = 0;
168 gridbag.setConstraints(date, c);
169 _center.add(date);
170
171 // holder for labels
172 JLabel label;
173
174 label = new javax.swing.JLabel("--- CPU ---", JLabel.CENTER);
175 c.gridy = 1;
176 gridbag.setConstraints(label, c);
177 _center.add(label);
178
179 // add all the DataComponents that we know about
180 JPanel cpu = new JPanel();
181 cpu.setLayout(new BoxLayout(cpu, BoxLayout.Y_AXIS));
182 addVisibleDataComponent(cpu, new CPUDataComponent("CPU Idle", "packet.cpu.idle"));
183 addVisibleDataComponent(cpu, new CPUDataComponent("CPU User", "packet.cpu.user"));
184 addVisibleDataComponent(cpu, new CPUDataComponent("CPU Kernel", "packet.cpu.kernel"));
185 addVisibleDataComponent(cpu, new CPUDataComponent("CPU i/o wait", "packet.cpu.iowait"));
186 addVisibleDataComponent(cpu, new CPUDataComponent("CPU swapping", "packet.cpu.swap"));
187 c.gridy = 2;
188 gridbag.setConstraints(cpu, c);
189 _center.add(cpu);
190
191 label = new javax.swing.JLabel("--- Load ---", JLabel.CENTER);
192 c.gridy = 3;
193 gridbag.setConstraints(label, c);
194 _center.add(label);
195
196 Box loadData = Box.createHorizontalBox();
197 addVisibleDataComponent(loadData, new ProcessesDataComponent("1 minute", "packet.load.load1"));
198 addVisibleDataComponent(loadData, new ProcessesDataComponent("5 minutes", "packet.load.load5"));
199 addVisibleDataComponent(loadData, new ProcessesDataComponent("15 minutes", "packet.load.load15"));
200
201 c.gridy = 4;
202 gridbag.setConstraints(loadData, c);
203 _center.add(loadData);
204
205 label = new javax.swing.JLabel("--- Processes ---", JLabel.CENTER);
206 c.gridy = 5;
207 gridbag.setConstraints(label, c);
208 _center.add(label);
209
210 Box processesData = Box.createHorizontalBox();
211 addVisibleDataComponent(processesData, new ProcessesDataComponent("Total", "packet.processes.total"));
212 addVisibleDataComponent(processesData, new ProcessesDataComponent("Running", "packet.processes.cpu"));
213 addVisibleDataComponent(processesData, new ProcessesDataComponent("Sleeping", "packet.processes.sleeping"));
214 addVisibleDataComponent(processesData, new ProcessesDataComponent("Stopped", "packet.processes.stopped"));
215 addVisibleDataComponent(processesData, new ProcessesDataComponent("Zombie", "packet.processes.zombie"));
216 c.gridy = 6;
217 gridbag.setConstraints(processesData, c);
218 _center.add(processesData);
219
220 label = new javax.swing.JLabel("--- Memory ---", JLabel.CENTER);
221 c.gridy = 7;
222 gridbag.setConstraints(label, c);
223 _center.add(label);
224
225 // these next two are passed the non-visible datacomponents
226 JPanel memory = new JPanel();
227 memory.setLayout(new BoxLayout(memory, BoxLayout.Y_AXIS));
228 addVisibleDataComponent(memory, new StorageDataComponent("Memory in use", "packet.memory.free", "packet.memory.total","Mb"));
229 addVisibleDataComponent(memory, new StorageDataComponent("Swap in use", "packet.swap.free", "packet.swap.total", "Mb"));
230 addVisibleDataComponent(memory, new StringDataComponent("Number of pages in", "packet.pages.swapins"));
231 addVisibleDataComponent(memory, new StringDataComponent("Number of pages out", "packet.pages.swapouts"));
232 // theses next two are DataComponents, but not VisibleDataComponents
233 // this is because they hold the value but do NOT display it
234 // just so we ignore the data, because the StorageDataComponent handles it
235 addDataComponent(new StringDataComponent("packet.memory.total", "packet.memory.total"));
236 addDataComponent(new StringDataComponent("packet.memory.used", "packet.memory.used"));
237 // maybe this one should be used somewhere?
238 addDataComponent(new StringDataComponent("packet.memory.cache", "packet.memory.cache"));
239 addDataComponent(new StringDataComponent("packet.swap.total", "packet.swap.total"));
240 addDataComponent(new StringDataComponent("packet.swap.used", "packet.swap.used"));
241 c.gridy = 8;
242 gridbag.setConstraints(memory, c);
243 _center.add(memory);
244
245 label = new javax.swing.JLabel("--- Users ---", JLabel.CENTER);
246 c.gridy = 9;
247 gridbag.setConstraints(label, c);
248 _center.add(label);
249
250 JPanel users = new JPanel();
251 users.setLayout(new BoxLayout(users, BoxLayout.Y_AXIS));
252 addVisibleDataComponent(users, new StringDataComponent("Number of users", "packet.users.count"));
253 UsersDataComponent userList = new UsersDataComponent("User List", "packet.users.list");
254 addVisibleDataComponent(users, userList);
255 c.gridy = 10;
256 gridbag.setConstraints(users, c);
257 _center.add(users);
258
259 label = new javax.swing.JLabel("--- Disks ---", JLabel.CENTER);
260 c.gridy = 11;
261 gridbag.setConstraints(label, c);
262 _center.add(label);
263 c.gridy = 12;
264 gridbag.setConstraints(_disks, c);
265 _center.add(_disks);
266
267 label = new javax.swing.JLabel("--- System Services ---", JLabel.CENTER);
268 c.gridy = 13;
269 gridbag.setConstraints(label, c);
270 _center.add(label);
271 c.gridy = 14;
272 gridbag.setConstraints(_services, c);
273 _center.add(_services);
274
275 // everything else we get is "extra", but we may still want to display it
276 if (_extraData) {
277 label = new javax.swing.JLabel("--- Extra Data ---", JLabel.CENTER);
278 c.gridy = 15;
279 gridbag.setConstraints(label, c);
280 _center.add(label);
281 c.gridy = 16;
282 gridbag.setConstraints(_extra, c);
283 _center.add(_extra);
284 }
285
286 // a bit of a gap, then a banner to advertise the product
287 c.gridy=17;
288 Component spacer = Box.createRigidArea(new Dimension(468, 30));
289 gridbag.setConstraints(spacer,c);
290 _center.add(spacer);
291 c.gridy=18;
292 JLabel image = new JLabel(new ImageIcon(getClass().getResource("/resources/banner3.gif")));
293 gridbag.setConstraints(image,c);
294 _center.add(image);
295 }
296
297 //---PUBLIC METHODS---
298
299 /**
300 * This method takes an XMLPacket containing
301 * information about the host this HostDisplayPanel
302 * is currently displaying. It then updates all of the
303 * components with the new values.
304 *
305 * It also adds a standard StringDataComponent, should
306 * an attribute come up that there are no DataComponents
307 * associated with.
308 *
309 * @param packet the XML packet
310 * @return if the update was sucessful
311 */
312 public boolean updateHost(XMLPacket packet) {
313 // set that everything is ok so far
314 boolean displaySucessful = true;
315
316 // a simple way to handle heatbeats - this WILL change
317 if ((packet.getParam("packet.attributes.type")).equals("heartbeat")) {
318 _heartbeatTimer.reset();
319 if(_heartbeatTimerThread == null){
320 _heartbeatTimerThread = new Thread(_heartbeatTimer);
321 _heartbeatTimerThread.start();
322 }
323 displaySucessful = processPacket(packet);
324
325 // must be a normal data packet, update the display
326 } else if((packet.getParam("packet.attributes.type")).equals("data")) {
327 displaySucessful = processPacket(packet);
328 _dataTimer.reset();
329 if(_dataTimerThread == null){
330 _dataTimerThread = new Thread(_dataTimer);
331 _dataTimerThread.start();
332 }
333 }
334 return displaySucessful;
335 }
336
337 //---PRIVATE METHODS---
338
339 /**
340 * Process an incoming packet, updates the components.
341 * If extra data is configured to be displayed, it will
342 * create a new StringDataComponent to display the data.
343 *
344 * @param packet the packet to process
345 *
346 * @return if the proceesing was successful
347 */
348 private boolean processPacket(XMLPacket packet) {
349 // iterate over the packets data
350 boolean displaySucessful = true;
351 Set packetSet = packet.getSet();
352 Iterator i = packetSet.iterator();
353 while (i.hasNext()) {
354 String dataKey = (String) i.next();
355
356 // if there are no components looking after this data
357 // create a new StringDataComponent for it
358 if(!_components.containsKey(dataKey)) {
359 // check if its a disk drive, if it is then we need to deal with it
360 if(dataKey.startsWith("packet.disk.p")) {
361 createDiskPanel(dataKey, packet);
362
363 // !check for services here! to display
364 } else if(dataKey.startsWith("packet.services.")) {
365 createServicesPanel(dataKey);
366
367 } else if (_extraData) {
368 addVisibleDataComponent(_extra, new StringDataComponent(dataKey, dataKey));
369 }
370 }
371
372 // try and update the component, if it doesn't like what it gets
373 // warn the user and set that this was an unsucessful display
374 if(_components.containsKey(dataKey)) {
375
376 try {
377 ((DataComponent) _components.get(dataKey)).setValue(packet);
378 } catch (DataFormatException e) {
379 Conient.addMessage("WARNING{host display}: " + e.getMessage());
380 displaySucessful = false;
381 }
382 }
383 }
384 return displaySucessful;
385 }
386
387 /**
388 * Adds a DataComponent to the list of already
389 * known data components. The list is aware of
390 * what packet attributes that a DataComponent
391 * is looking after.
392 *
393 * @param ref the packet attribute that this Component looks after
394 * @param dataComponent the actual DataComponent
395 */
396 private void addDataComponent(DataComponent dataComponent) {
397 _components.put(dataComponent.getPacketAttribute(), dataComponent);
398 }
399
400 /**
401 * Adds a DataComponent to the list of already
402 * known data components. The list is aware of
403 * what packet attributes that a DataComponent
404 * is looking after.
405 *
406 * Used for VISIBLE data components, as they are added to the display.
407 *
408 * @param ref the packet attribute that this Component looks after
409 * @param dataComponent the actual DataComponent
410 */
411 public void addVisibleDataComponent(Container holder, VisibleDataComponent dataComponent) {
412 _components.put(((DataComponent) dataComponent).getPacketAttribute(), (DataComponent) dataComponent);
413 SwingSafeAdd task = new SwingSafeAdd(holder, dataComponent);
414 SwingUtilities.invokeLater(task);
415 }
416
417 /**
418 * Creates the disk components and adds them
419 * do the list of components. It also displays
420 * any relavant component.
421 *
422 * When a packet attribute is new to the system
423 * and when it starts "packet.disk.p" then this
424 * method is called. Thus it then accounts for
425 * all attributes relating to that new disk.
426 *
427 * @param attribute the name of the attrivbute first encountered
428 * @param packet the XMLPacket the data is being pulled from
429 */
430 private void createDiskPanel(String attribute, XMLPacket packet) {
431 String diskNumber = "";
432
433 // pos is after "packet.disk.p"
434 int pos = 13;
435 while (attribute.charAt(pos) != '.') {
436 diskNumber = diskNumber + attribute.charAt(pos);
437 pos++;
438 }
439 String devAttribute = "packet.disk.p" + diskNumber + ".attributes.name";
440 String mountAttribute = "packet.disk.p" + diskNumber + ".attributes.mount";
441 String totalAttribute = "packet.disk.p" + diskNumber + ".attributes.kbytes";
442
443 // the only visible component
444 String availAttribute = "packet.disk.p" + diskNumber + ".attributes.avail";
445 DiskDataComponent disk = new DiskDataComponent("Disk", availAttribute, totalAttribute, mountAttribute, devAttribute , "Mb", 1024);
446 addVisibleDataComponent(_disks, disk);
447
448 // currently this data isn't useful, so we don't display it
449 // but we add it so that it is forgotten about
450 addDataComponent(new StringDataComponent(devAttribute, devAttribute));
451 addDataComponent(new StringDataComponent(mountAttribute, mountAttribute));
452 addDataComponent(new StringDataComponent(totalAttribute, totalAttribute));
453
454 // add any further bits of data about this disk so we
455 // don't try and do something with them later
456 // -- this is not that tidy ;)
457 Set packetSet = packet.getSet();
458 Iterator i = packetSet.iterator();
459 while (i.hasNext()) {
460 String dataKey = (String) i.next();
461 if(dataKey.startsWith("packet.disk.p" + diskNumber +".") && !_components.containsKey(dataKey)) {
462 addDataComponent(new StringDataComponent(dataKey, dataKey));
463 }
464 }
465 }
466
467 /**
468 * Creates the disk components and adds them
469 * do the list of components. It also displays
470 * any relavant component.
471 *
472 * When a packet attribute is new to the system
473 * and when it starts "packet.disk.p" then this
474 * method is called. Thus it then accounts for
475 * all attributes relating to that new disk.
476 *
477 * @param attribute the name of the attrivbute first encountered
478 */
479 private void createServicesPanel(String attribute) {
480 String serviceType = "";
481
482 // pos is after "packet.services."
483 int pos = 16;
484 while (attribute.charAt(pos) != '.') {
485 serviceType = serviceType + attribute.charAt(pos);
486 pos++;
487 }
488
489 String statusAttribute = "packet.services." + serviceType + ".attributes.status";
490 // we hide this as the service data component uses this attribute
491 addDataComponent(new StringDataComponent(serviceType + " service status", statusAttribute));
492
493 ServiceDataComponent service = new ServiceDataComponent(serviceType, "packet.services." + serviceType + ".attributes.message", statusAttribute);
494 addVisibleDataComponent(_services, service);
495 }
496
497 //---ACCESSOR/MUTATOR METHODS---
498
499 //---ATTRIBUTES---
500
501 /**
502 * The components that we already know about
503 * connected with the attributes they care about
504 * are stored here.
505 */
506 private HashMap _components = new HashMap();
507
508 /**
509 * The north panel, currently used for the platform info button.
510 */
511 private final JPanel _north = new JPanel();
512
513 /**
514 * The centre panel, where all the data is displayed.
515 */
516 private final JPanel _center = new JPanel();
517
518 /**
519 * The countdown timer for heartbeats
520 */
521 private final PacketTimer _heartbeatTimer;
522
523 /**
524 * The countdown timer for normal data packets
525 */
526 private final PacketTimer _dataTimer;
527
528 /**
529 * A place for the heartbeat timer thread
530 */
531 private Thread _heartbeatTimerThread = null;
532
533 /**
534 * A place for the data timer thread
535 */
536 private Thread _dataTimerThread = null;
537
538 /**
539 * The hostname this instance is keeping data for
540 */
541 private final String _hostName;
542
543 /**
544 * The disks panel
545 */
546 private final JPanel _disks = new JPanel();
547 {
548 _disks.setLayout(new BoxLayout(_disks, BoxLayout.Y_AXIS));
549 }
550
551 /**
552 * The extra panel, used to display unknown data in the packet
553 */
554 private final JPanel _extra = new JPanel();
555 {
556 _extra.setLayout(new BoxLayout(_extra, BoxLayout.Y_AXIS));
557 }
558
559 /**
560 * The services panel, currently used to display host service information
561 * from heartbeat packets.
562 */
563 private final JPanel _services = new JPanel();
564 {
565 _services.setLayout(new BoxLayout(_services, BoxLayout.Y_AXIS));
566 }
567
568 /**
569 * Whether we a worrying about "extra" data
570 * by default we don't, but we look in the configuration
571 * in the constructor.
572 */
573 private boolean _extraData = false;
574
575 //---STATIC ATTRIBUTES---
576
577 }