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.41
Committed: Sat May 18 18:15:56 2002 UTC (22 years ago) by tdb
Branch: MAIN
Changes since 1.40: +22 -3 lines
Log Message:
i-scream is now licensed under the GPL. I've added the GPL headers to every
source file, and put a full copy of the license in the appropriate places.
I think I've covered everything. This is going to be a mad commit ;)

File Contents

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