source: branches/0.4/web/addons/job_monarch/libtoga.php @ 746

Last change on this file since 746 was 746, checked in by ramonb, 9 years ago
  • replaced time intensive for loop
  • only need to check 1 host really
  • Property svn:keywords set to Id
File size: 69.0 KB
Line 
1<?php
2/*
3 *
4 * This file is part of Jobmonarch
5 *
6 * Copyright (C) 2006-2013  Ramon Bastiaans
7 *
8 * Jobmonarch is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * Jobmonarch is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21 *
22 * SVN $Id: libtoga.php 746 2013-03-25 16:39:25Z ramonb $
23 *
24 */
25
26
27class HTTPVariables
28{
29    var $clustername, $metricname;
30    var $restvars, $httpvars;
31
32    function HTTPVariables( $httpvars, $getvars )
33    {
34        $this->restvars        = array();
35
36        $this->clustername    = isset( $httpvars["c"] ) ? $httpvars["c"] : $getvars["c"];
37        $this->metricname    = isset( $httpvars["m"] ) ? $httpvars["m"] : $getvars["m"];
38
39        if( count( $httpvars ) > 0 )
40        {
41            foreach( $httpvars as $httpvar => $httpval )
42            {
43                if( $httpval )
44                {
45                    $this->restvars[$httpvar] = $httpval;
46                }
47            }
48        }
49
50        if( count( $getvars ) > 0 )
51        {
52            foreach( $getvars as $getvar => $getval )
53            {
54                if( $getval )
55                {
56                    $this->restvars[$getvar] = $getval;
57                }
58            }
59        }
60    }
61
62    function getClusterName()
63    {
64        return $this->clustername;
65    }
66
67    function getMetricName()
68    {
69        return $this->metricname;
70    }
71
72    function getHttpVar( $var )
73    {
74        if( isset( $this->restvars[$var] ) )
75        {
76            return $this->restvars[$var];
77        }
78        else
79        {
80            return null;
81        }
82    }
83}
84
85$CLUSTER_CONFS    = array();
86
87ini_set("memory_limit","500M");
88set_time_limit(0);
89
90// Monarch's conf
91//
92include_once "./conf.php";
93include_once "./version.php";
94
95global $GANGLIA_PATH;
96global $RRDTOOL;
97global $JOB_ARCHIVE_DIR;
98global $JOB_ARCHIVE_DBASE;
99global $skan_str;
100global $x_first, $y_first;
101global $CLUSTER_CONFS;
102
103$my_dir = getcwd();
104
105// Load Ganglia's PHP
106chdir( $GANGLIA_PATH );
107
108include_once "./eval_conf.php";
109include_once "./functions.php";
110include_once "./ganglia.php";
111include_once "./get_context.php";
112
113$context = 'cluster';
114include_once "./get_ganglia.php";
115
116// Back to our PHP
117chdir( $my_dir );
118
119global $SMALL_CLUSTERIMAGE_MAXWIDTH, $SMALL_CLUSTERIMAGE_NODEWIDTH, $DATA_SOURCE, $HTTP_GET_VARS, $_GET;
120$httpvars = new HTTPVariables( $HTTP_GET_VARS, $_GET );
121
122// Set cluster context so that Ganglia will
123// provide us with the correct metrics array
124//
125global $context, $clustername, $reports;
126
127global $default_metric;
128
129// Ganglia's array of host metrics
130//
131global $metrics, $hosts_up;
132global $start;
133
134global $DATETIME_FORMAT;
135
136function makeDate( $time )
137{
138    global $DATETIME_FORMAT;
139    return strftime( $DATETIME_FORMAT, $time );
140}
141
142
143class TarchDbase
144{
145    var $ip, $dbase, $conn;
146
147    function TarchDbase( $ip = null, $dbase = null )
148    {
149        global $CLUSTER_CONFS, $clustername;
150        global $JOB_ARCHIVE_DBASE;
151
152        // Import cluster specific settings
153        //
154        foreach( $CLUSTER_CONFS as $confcluster => $conffile )
155        {
156            if( strtolower( trim($this->clustername) ) == strtolower(trim($confcluster)) )
157            {
158                include_once $conffile;
159            }
160        }
161
162        $db_fields = explode( '/', $JOB_ARCHIVE_DBASE );
163
164        $this->ip    = $db_fields[0];
165        $this->dbase    = $db_fields[1];
166        $this->conn    = null;
167    }
168
169    function connect()
170    {
171        if( $this->ip == null )
172            $this->conn = pg_connect( "dbname=".$this->dbase );
173        else
174            $this->conn = pg_connect( "host=".$this->ip." dbname=".$this->dbase );
175    }
176
177    function searchDbase( $id = null, $queue = null, $owner = null, $name = null, $start_from_time = null, $start_to_time = null, $end_from_time = null, $end_to_time = null )
178    {
179        global $SEARCH_RESULT_LIMIT;
180
181        if( $id )
182        {
183            $select_query = "SELECT job_id FROM jobs WHERE job_id = '$id' AND job_status = 'F'";
184            $this->resultcount = 1;
185        }
186        else
187        {
188            $query_args = array();
189           
190            if( $queue )
191            {
192                $query_args[] = "job_queue ='$queue'";
193            }
194            if( $owner )
195            {
196                $query_args[] = "job_owner ='$owner'";
197            }
198            if( $name )
199            {
200                $query_args[] = "job_name = '$name'";
201            }
202            if( $start_from_time )
203            {
204                $query_args[] = "job_start_timestamp >= $start_from_time";
205            }
206            if( $start_to_time )
207            {
208                $query_args[] = "job_start_timestamp <= $start_to_time";
209            }
210            if( $end_from_time )
211            {
212                $query_args[] = "job_stop_timestamp >= $end_from_time";
213            }
214            if( $end_to_time )
215            {
216                $query_args[] = "job_stop_timestamp <= $end_to_time";
217            }
218
219            $query = "FROM jobs WHERE job_status = 'F' AND ";
220            $extra_query_args = '';
221
222            foreach( $query_args as $myquery )
223            {
224                if( $extra_query_args == '' )
225                {
226                    $extra_query_args = $myquery;
227                }
228                else
229                {
230                    $extra_query_args .= " AND ".$myquery;
231                }
232            }
233            $query .= $extra_query_args;
234
235            $count_result_idname = "COUNT(job_id)";
236            $select_result_idname = "job_id";
237
238            $count_query = "SELECT " . $count_result_idname . " " . $query;
239
240            $count_result = $this->queryDbase( $count_query );
241            $this->resultcount = (int) $count_result[0]['count'];
242
243            $select_query = "SELECT " . $select_result_idname . " " . $query . " ORDER BY job_id DESC LIMIT " . $SEARCH_RESULT_LIMIT;
244        }
245
246        $ids = $this->queryDbase( $select_query );
247
248        $ret = array();
249
250        foreach( $ids as $crow)
251        {
252            $ret[] = $crow['job_id'];
253        }
254
255        return $ret;
256    }
257
258    function getNodesForJob( $jobid )
259    {
260        $result = $this->queryDbase( "SELECT node_id FROM job_nodes WHERE job_id = '$jobid'" );
261
262        $nodes = array();
263
264        foreach( $result as $result_row ) 
265        {
266            $nodes[] = $this->getNodeArray( $result_row['node_id'] );
267        }
268
269        return $nodes;
270    }
271
272    function getJobsForNode( $nodeid )
273    {
274        $result = $this->queryDbase( "SELECT job_id FROM job_nodes WHERE node_id = '$nodeid'" );
275
276        $jobs = array();
277
278        foreach( $result as $result_row )
279        {
280            $jobs[] = $this->getJobArray( $result_row['job_id'] );
281        }
282        return $jobs;
283    }
284
285    function getJobArray( $id )
286    {
287        $result = $this->queryDbase( "SELECT * FROM jobs WHERE job_id = '$id'" );
288
289        return ( $this->makeArray( $result[0] ) );
290    }
291
292    function getNodeArray( $id )
293    {
294        $result = $this->queryDbase( "SELECT * FROM nodes WHERE node_id = '$id'" );
295
296        return ( $this->makeArray( $result[0] ) );
297    }
298
299    function makeArray( $result_row )
300    {
301        $myar = array();
302
303        foreach( $result_row as $mykey => $myval )
304        {
305            $map_key = explode( '_', $mykey );
306
307            $rmap_key = array_reverse( $map_key );
308            array_pop( $rmap_key );
309            $map_key = array_reverse( $rmap_key );
310           
311            $newkey = implode( '_', $map_key );
312           
313            $myar[$newkey] = $result_row[$mykey];
314        }
315
316        return $myar;
317    }
318
319    function queryDbase( $query )
320    {
321        $result_rows = array();
322   
323        if( !$this->conn )
324        {
325            $this->connect();
326        }
327
328        $result = pg_query( $this->conn, $query );
329
330        while ($row = pg_fetch_assoc($result))
331        {
332            $result_rows[] = $row;
333        }
334
335        return $result_rows;
336    }
337}
338
339class TarchRrdGraph
340{
341    var $rrdbin, $rrdvalues, $clustername, $hostname, $tempdir, $tarchdir, $metrics;
342
343    function TarchRrdGraph( $clustername, $hostname )
344    {
345        global $conf;
346        global $JOB_ARCHIVE_DIR;
347
348        $this->rrdbin        = $conf['rrdtool'];
349        $this->rrdvalues    = array();
350        $this->tarchdir        = $JOB_ARCHIVE_DIR;
351        $this->clustername    = $clustername;
352        $this->hostname        = $hostname;
353    }
354
355    function doCmd( $command )
356    {
357        $pipe = popen( $command . ' 2>&1', 'r' );
358
359        if (!$pipe)
360        {
361            print "pipe failed.";
362            return "";
363        }
364
365        $output = '';
366
367        while(!feof($pipe))
368        {
369            $output .= fread($pipe, 1024);
370        }
371
372        pclose($pipe);
373
374        $output = explode( "\n", $output );
375
376        return $output;
377    }
378
379    function dirList( $dir )
380    {
381        $dirlist = array();
382
383        if ($handle = opendir( $dir ))
384        {
385            while (false !== ($file = readdir($handle)))
386            {
387                if ($file != "." && $file != "..")
388                {
389                    $dirlist[] = $file;
390                }
391            }
392            closedir($handle);
393        }
394
395        return $dirlist;
396    }
397
398    function getTimePeriods( $start, $end )
399    {
400        $times = array();
401        $dirlist = $this->dirList( $this->tarchdir . '/' . $this->clustername . '/' . $this->hostname );
402
403        $first = 0;
404        $last = 9999999999999;
405
406        foreach( $dirlist as $dir )
407        {
408            if( $dir > $first and $dir <= $start )
409            {
410                $first = $dir;
411            }
412            if( $dir < $last and $dir >= $end )
413            {
414                $last = $dir;
415            }
416        }
417
418        foreach( $dirlist as $dir )
419        {
420            if( $dir >= $first and $dir <= $last and !array_key_exists( $dir, $times ) )
421            {
422                $times[] = $dir;
423            }
424        }
425
426        sort( $times );
427
428        return $times;
429    }
430
431    function getRrdDirs( $start, $stop )
432    {
433        $timess = $this->getTimePeriods( $start, $stop );
434
435        $rrd_files = array();
436
437        foreach( $timess as $time )
438        {
439            $rrd_files[] = $this->tarchdir . '/' . $this->clustername . '/' . $this->hostname. '/'.$time;
440        }
441
442        return $rrd_files;
443    }
444
445    function getRrdFiles( $metric, $start, $stop )
446    {
447        $times = $this->getTimePeriods( $start, $stop );
448
449        $rrd_files = array();
450
451        foreach( $times as $time )
452        {
453            $rrd_files[] = $this->tarchdir . '/' . $this->clustername . '/' . $this->hostname . '/' .$time. '/' . $metric. '.rrd';
454        }
455
456        return $rrd_files;
457    }
458}
459
460class DataSource
461{
462    var $data, $ip, $port;
463
464    function DataSource()
465    {
466        global $DATA_SOURCE, $clustername;
467
468        $ds_fields     = explode( ':', $DATA_SOURCE );
469
470        $ds_ip         = $ds_fields[0];
471        $ds_port       = $ds_fields[1];
472
473        $this->ip       = $ds_ip;
474        $this->port     = $ds_port;
475        $this->clustername = $clustername;
476    }
477
478    function getData()
479    {
480        $errstr        = '';
481        $errno         = 0;
482        $timeout       = 3;
483
484        $fp = fsockopen( $this->ip, $this->port, $errno, $errstr, $timeout );
485
486        if( !$fp )
487        {
488            echo 'Unable to connect to '.$this->ip.':'.$this->port;
489            return;
490        }
491
492        if( $this->port == '8652' )
493        {
494            $request = "/" . $this->clustername . "\n";
495            $rc = fputs($fp, $request);
496            if (!$rc)
497            {
498                $error = "Could not sent request to gmetad: $errstr";
499                if ($debug) print "<br/>DEBUG: $error\n";
500                   return FALSE;
501            }
502        }
503
504        stream_set_timeout( $fp, 30 );
505
506        while ( !feof( $fp ) )
507        {
508            $data .= fread( $fp, 16384 );
509        }
510
511        fclose( $fp );
512
513        return $data;
514    }
515}
516
517class DataGatherer
518{
519    var $xmlhandler, $data, $httpvars;
520
521    function DataGatherer( $cluster )
522    {
523        $this->cluster    = $cluster;
524        $this->httpvars = $httpvars;
525    }
526
527    function parseXML( $data )
528    {
529
530        $this->parser         = xml_parser_create();
531        $this->xmlhandler     = new TorqueXMLHandler( $this->cluster );
532
533        xml_set_element_handler( $this->parser, array( &$this->xmlhandler, 'startElement' ), array( &$this->xmlhandler, 'stopElement' ) );
534
535        if ( !xml_parse( $this->parser, $data ) )
536        {
537            $error = sprintf( 'XML error: %s at %d', xml_error_string( xml_get_error_code( $this->parser ) ), xml_get_current_line_number( $this->parser ) );
538        }
539    }
540
541    function printInfo()
542    {
543        $handler = $this->xmlhandler;
544        $handler->printInfo();
545    }
546
547    function getUsingFQDN()
548    {
549        $handler = $this->xmlhandler;
550        return $handler->getUsingFQDN();
551    }
552
553    function getNodes()
554    {
555        $handler = $this->xmlhandler;
556        return $handler->getNodes();
557    }
558
559    function getNode( $node )
560    {
561        $handler = $this->xmlhandler;
562        return $handler->getNode( $node );
563    }
564
565    function getCpus()
566    {
567        $handler = $this->xmlhandler;
568        return $handler->getCpus();
569    }
570
571    function getJobs()
572    {
573        $handler = $this->xmlhandler;
574        return $handler->getJobs();
575    }
576
577    function getJob( $job )
578    {
579        $handler = $this->xmlhandler;
580        return $handler->getJob( $job );
581    }
582
583    function getHeartbeat()
584    {
585        $handler = $this->xmlhandler;
586        return $handler->getHeartbeat();
587    }
588
589    function isJobmonRunning()
590    {
591        $handler = $this->xmlhandler;
592        return $handler->isJobmonRunning();
593    }
594}
595
596class TorqueXMLHandler
597{
598    var $clusters, $heartbeat, $nodes, $jobs, $clustername, $proc_cluster;
599
600    function TorqueXMLHandler( $clustername )
601    {
602        $this->jobs        = array();
603        $this->clusters     = array();
604        $this->nodes         = array();
605        $this->heartbeat     = array();
606        $this->down_nodes    = array();
607        $this->offline_nodes    = array();
608        $this->clustername    = $clustername;
609        $this->fqdn        = 1;
610    }
611
612    function getUsingFQDN()
613    {
614        return $this->fqdn;
615    }
616
617    function getCpus()
618    {
619        $cpus = 0;
620
621        if( isset( $this->jobs ) && count( $this->jobs ) > 0 )
622        {
623            foreach( $this->jobs as $jobid=>$jobattrs )
624            {
625                $nodes    = count( $jobattrs['nodes'] );
626                $ppn    = (int) $jobattrs['ppn'] ? $jobattrs['ppn'] : 1;
627                $mycpus    = $nodes * $ppn;
628
629                $cpus    = $cpus + $mycpus;
630            }
631        }
632    }
633
634    function isJobmonRunning()
635    {
636        if (isset( $this->heartbeat['time'] ))
637        {
638            return 1;
639        }
640        else
641        {
642            return 0;
643        }
644    }
645
646    function makeHostname( $thostname, $tdomain=null )
647    {
648        // Should hostname be FQDN or short w/o domain
649        //
650        $nodes = &$this->nodes;
651
652        $fqdn = 1;
653
654        //$tdomain = explode( '.', $thostname );
655        //
656        // TODO?: extract domain from hostname or something?
657
658        if( $tdomain )
659        {
660            $domain_len    = 0 - strlen( $tdomain );
661
662            // Let's see if Ganglia use's FQDN or short hostnames
663            //
664            foreach( $nodes as $hostname => $nimage )
665            {
666                if( substr( $hostname, $domain_len ) != $tdomain )
667                {
668                    $fqdn    = 0;
669                }
670            }
671        }
672        else
673        {
674            $fqdn    = 0;
675        }
676   
677        if( $tdomain && $fqdn )
678        {
679            if( substr( $thostname, $domain_len ) != $tdomain )
680            {
681                $thostname = $thostname . '.'.$tdomain;
682            } 
683            else
684            {
685                $thostname = $thostname;
686            }
687        }
688
689        return $thostname;
690    }
691
692    function startElement( $parser, $name, $attrs )
693    {
694        $jobs = $this->jobs;
695        $nodes = $this->nodes;
696
697        if( isset( $attrs['TN'] ) )
698        {
699            if ( $attrs['TN'] )
700            {
701                // Ignore dead metrics. Detect and mask failures.
702                if ( $attrs['TN'] > $attrs['TMAX'] * 4 )
703                {
704                    return;
705                }
706            }
707        }
708
709        $jobid = null;
710
711        if( $name == 'CLUSTER' )
712        {
713            $this->proc_cluster = $attrs['NAME'];
714        }
715        else if( $name == 'HOST' and $this->proc_cluster == $this->clustername)
716        {
717            $hostname = $attrs['NAME'];
718
719            $location = $attrs['LOCATION'];
720
721            if( !isset( $nodes[$hostname] ) )
722            {
723                $nodes[$hostname] = new NodeImage( $this->proc_cluster, $hostname );
724            }
725        }
726        else if( $name == 'METRIC' and strstr( $attrs['NAME'], 'zplugin_monarch' ) and $this->proc_cluster == $this->clustername )
727        {
728            if( strstr( $attrs['NAME'], 'zplugin_monarch_heartbeat' ) )
729            {
730                $this->heartbeat['time'] = $attrs['VAL'];
731            }
732            else if( strstr( $attrs['NAME'], 'zplugin_monarch_down' ) )
733            {
734                $fields        = explode( ' ', $attrs['VAL'] );
735
736                $nodes_down    = array();
737                $down_domain    = null;
738
739                foreach( $fields as $f )
740                {
741                    $togavalues    = explode( '=', $f );
742
743                    $toganame    = $togavalues[0];
744                    $togavalue    = $togavalues[1];
745
746                    if( $toganame == 'nodes' )
747                    {
748                        $mynodes = explode( ';', $togavalue );
749
750                        foreach( $mynodes as $node )
751                        {
752                            $nodes_down[] = $node;
753                        }
754                    }
755                    else if( $toganame == 'domain' )
756                    {
757                        $down_domain = $togavalue;
758                    }
759                    else if( $toganame == 'reported' )
760                    {
761                        if( !isset( $this->down_nodes['heartbeat'] ) )
762                        {
763                            $this->down_nodes[$togavalue]    = array( $nodes_down, $down_domain );
764                        }
765                    }
766                }
767            }
768            else if( strstr( $attrs['NAME'], 'zplugin_monarch_offline' ) )
769            {
770                $fields        = explode( ' ', $attrs['VAL'] );
771
772                $nodes_offline    = array();
773                $offline_domain    = null;
774
775                foreach( $fields as $f )
776                {
777                    $togavalues    = explode( '=', $f );
778
779                    $toganame    = $togavalues[0];
780                    $togavalue    = $togavalues[1];
781
782                    if( $toganame == 'nodes' )
783                    {
784                        $mynodes = explode( ';', $togavalue );
785
786                        foreach( $mynodes as $node )
787                        {
788                            $nodes_offline[] = $node;
789                        }
790                    }
791                    else if( $toganame == 'domain' )
792                    {
793                        $offline_domain = $togavalue;
794                    }
795                    else if( $toganame == 'reported' )
796                    {
797                        if( !isset( $this->offline_nodes['heartbeat'] ) )
798                        {
799                            $this->offline_nodes[$togavalue] = array( $nodes_offline, $offline_domain );
800                        }
801                    }
802                }
803            }
804            else if( strstr( $attrs['NAME'], 'zplugin_monarch_job' ) )
805            {
806                sscanf( $attrs['NAME'], 'zplugin_monarch_job_%d_%s$', $monincr, $jobid );
807
808                if( !isset( $jobs[$jobid] ) )
809                {
810                    $jobs[$jobid] = array();
811                }
812
813                $fields = explode( ' ', $attrs['VAL'] );
814
815                foreach( $fields as $f )
816                {
817                    $togavalues = explode( '=', $f );
818
819                    $toganame = $togavalues[0];
820                    $togavalue = $togavalues[1];
821
822                    if( $toganame == 'nodes' )
823                    {
824                        if( $jobs[$jobid]['status'] == 'R' )
825                        {
826                            if( !isset( $jobs[$jobid][$toganame] ) )
827                            {
828                                $jobs[$jobid][$toganame] = array();
829                            }
830
831                            $mynodes = explode( ';', $togavalue );
832
833                            foreach( $mynodes as $node )
834                            {
835                                if( !in_array( $node, $jobs[$jobid][$toganame] ) )
836                                {
837                                    array_push( $jobs[$jobid][$toganame], $node );
838                                }
839                            }
840
841                        }
842                        else if( $jobs[$jobid]['status'] == 'Q' )
843                        {
844                            $jobs[$jobid][$toganame] = $togavalue;
845                        }
846                    }
847                    else
848                    {
849                        $jobs[$jobid][$toganame] = $togavalue;
850                    }
851                }
852
853                if( isset( $jobs[$jobid]['nodes'] ) )
854                {
855                    $nr_nodes = count( $jobs[$jobid]['nodes'] );
856       
857                    if( $jobs[$jobid]['status'] == 'R' )
858                    {
859
860                        if( isset( $jobs[$jobid]['domain'] ) )
861                        {
862                            $domain        = $jobs[$jobid]['domain'];
863                            $domain_len    = 0 - strlen( $domain );
864
865                            $nodekeys     = array_keys( $nodes );
866
867                            $first_host    = $nodekeys[0];
868                            // Let's see if Ganglia use's FQDN or short hostnames
869                            //
870                            if( substr( $first_host, $domain_len ) != $domain )
871                            {
872                                $this->fqdn    = 0;
873                            }
874                        }
875                        else
876                        {
877                            $this->fqdn    = 0;
878                        }
879
880                        foreach( $jobs[$jobid]['nodes'] as $node )
881                        {
882
883                            // Only add domain name to the hostname if Ganglia is doing that too
884                            //
885                            if( $this->fqdn && isset( $jobs[$jobid]['domain'] ) )
886                            {
887                                if( substr( $node, $domain_len ) != $domain )
888                                {
889                                    $host = $node. '.'.$domain;
890                                } else
891                                {
892                                    $host = $node;
893                                }
894                            }
895                            else
896                            {
897                                $host    = $node;
898                            }
899
900                            if( !isset( $nodes[$host] ) )
901                            {
902                                $my_node = new NodeImage( $this->proc_cluster, $host );
903                            }
904                            else
905                            {
906                                $my_node = $nodes[$host];
907                            }
908
909                            if( !$my_node->hasJob( $jobid ) )
910                            {
911                                if( isset( $jobs[$jobid]['ppn'] ) )
912                                {
913                                    $my_node->addJob( $jobid, ((int) $jobs[$jobid]['ppn']) );
914                                }
915                                else
916                                {
917                                    $my_node->addJob( $jobid, 1 );
918                                }
919                            }
920
921                            $nodes[$host] = $my_node;
922                        }
923                    }
924                }
925            }
926        }
927        $this->jobs    = $jobs;
928        $this->nodes    = $nodes;
929    }
930
931    function stopElement( $parser, $name )
932    {
933        $nodes    = $this->nodes;
934
935        if( $name == "GANGLIA_XML" )
936        {
937            if( sizeof( $this->down_nodes ) > 0 )
938            {
939                foreach( $this->down_nodes as $reported => $dnodes )
940                {
941                    if( $reported == $this->heartbeat['time'] )
942                    {
943                        $domain = $dnodes[1];
944
945                        foreach( $dnodes[0] as $downhost )
946                        {
947                            $downhost = $this->makeHostname( $downhost, $domain );
948
949                            if( isset( $nodes[$downhost] ) )
950                            {
951                                // OMG PHP4 is fking stupid!
952                                // $nodes[$downhost]->setDown( 1 ) won't work here..
953                                //
954                                $mynode = $nodes[$downhost];
955                                $mynode->setDown( 1 );
956                                $nodes[$downhost] = $mynode;
957                            }
958                        }
959                    }
960                }
961            }
962
963            if( sizeof( $this->offline_nodes ) > 0 )
964            {
965                foreach( $this->offline_nodes as $reported => $onodes )
966                {
967                    if( $reported == $this->heartbeat['time'] )
968                    {
969                        $domain = $onodes[1];
970
971                        foreach( $onodes[0] as $offlinehost )
972                        {
973                            $offlinehost = $this->makeHostname( $offlinehost, $domain );
974
975                            if( isset( $nodes[$offlinehost] ) )
976                            {
977                                // OMG PHP4 is fking stupid!
978                                // $nodes[$offlinehost]->setDown( 1 ) won't work here..
979                                //
980                                $mynode = $nodes[$offlinehost];
981                                $mynode->setOffline( 1 );
982                                $nodes[$offlinehost] = $mynode;
983                            }
984                        }
985                    }
986                }
987            }
988        }
989
990        $this->nodes = $nodes;
991    }
992
993    function printInfo()
994    {
995        $jobs = &$this->jobs;
996
997        printf( "---jobs---\n" );
998
999        foreach( $jobs as $jobid => $job )
1000        {
1001            printf( "job %s\n", $jobid );
1002
1003            if( isset( $job['nodes'] ) )
1004            {
1005                foreach( $job['nodes'] as $node )
1006                {
1007                    $mynode = $this->nodes[$node];
1008                    $hostname = $mynode->getHostname();
1009                    $location = $mynode->getLocation();
1010
1011                    printf( "\t- node %s\tlocation %s\n", $hostname, $location );
1012                }
1013            }
1014        }
1015
1016        printf( "---nodes---\n" );
1017
1018        $nodes = &$this->nodes;
1019
1020        foreach( $nodes as $node )
1021        {
1022            $hostname = $node->getHostname();
1023            $location = $node->getLocation();
1024            $jobs = implode( ' ', $node->getJobs() );
1025            printf( "* node %s\tlocation %s\tjobs %s\n", $hostname, $location, $jobs );
1026        }
1027    }
1028
1029    function getNodes()
1030    {
1031        return $this->nodes;
1032    }
1033
1034    function getNode( $node )
1035    {
1036        $nodes = &$this->nodes;
1037
1038        if( isset( $nodes[$node] ) )
1039        {
1040            return $nodes[$node];
1041        }
1042        else
1043        {
1044            return NULL;
1045        }
1046    }
1047
1048    function getJobs()
1049    {
1050        return $this->jobs;
1051    }
1052
1053    function getJob( $job )
1054    {
1055        $jobs = &$this->jobs;
1056
1057        if( isset( $jobs[$job] ) )
1058        {
1059            return $jobs[$job];
1060        }
1061        else
1062        {
1063            return NULL;
1064        }
1065    }
1066
1067    function getHeartbeat()
1068    {
1069        return $this->heartbeat['time'];
1070    }
1071}
1072
1073class NodeImage
1074{
1075    var $image, $x, $y, $hostname, $jobs, $tasks, $showinfo;
1076
1077    function NodeImage( $cluster, $hostname )
1078    {
1079        global $SMALL_CLUSTERIMAGE_NODEWIDTH;
1080
1081        $this->jobs        = array();
1082        $this->tasks        = 0;
1083        $this->hostname        = $hostname;
1084        $this->clustername    = $cluster;
1085        $this->showinfo        = 1;
1086        $this->size        = $SMALL_CLUSTERIMAGE_NODEWIDTH;
1087        $this->down        = 0;
1088        $this->offline        = 0;
1089    }
1090
1091    function addJob( $jobid, $cpus )
1092    {
1093        $jobs        = &$this->jobs;
1094        $jobs[]        = $jobid;
1095        $this->jobs    = $jobs;
1096
1097        $this->addTask( $cpus );
1098    }
1099
1100    function hasJob( $jobid )
1101    {
1102        $jobfound = 0;
1103
1104        if( count( $this->jobs ) > 0 )
1105        {
1106            foreach( $this->jobs as $job )
1107            {
1108                if( $job == $jobid )
1109                {
1110                    $jobfound = 1;
1111                }
1112            }
1113        }
1114
1115        return $jobfound;
1116    }
1117
1118    function addTask( $cpus )
1119    {
1120        $this->tasks = $this->tasks + $cpus;
1121    }
1122    function setDown( $down )
1123    {
1124        $this->down = $down;
1125    }
1126    function isDown()
1127    {
1128        return $this->down;
1129    }
1130    function setOffline( $offline )
1131    {
1132        $this->offline = $offline;
1133    }
1134    function isOffline()
1135    {
1136        return $this->offline;
1137    }
1138    function setImage( $image )
1139    {
1140        $this->image = $image;
1141    }
1142    function setCoords( $x, $y )
1143    {
1144        $this->x = $x;
1145        $this->y = $y;
1146    }
1147    function getX()
1148    {
1149        return $this->x;
1150    }
1151    function getY()
1152    {
1153        return $this->y;
1154    }
1155
1156    function getImagemapArea()
1157    {
1158        $area_topleft        = $this->x . "," . $this->y;
1159        $area_bottomright    = ($this->x + $this->size) . "," . ($this->y + $this->size);
1160        $area_coords        = $area_topleft . "," . $area_bottomright;
1161
1162        $area_href        = "./?c=" . $this->clustername . "&h=" . $this->hostname;
1163
1164        $area_tooltip        = $this->hostname;
1165
1166        if( $this->down)
1167        {
1168            $area_tooltip        = $area_tooltip . ": DOWN";
1169        }
1170        else if( $this->offline )
1171        {
1172            $area_tooltip        = $area_tooltip . ": OFFLINE";
1173        }
1174
1175        $area_tooltip        = $area_tooltip . ": " . implode( " ", $this->jobs );
1176
1177        $tag_href        = "HREF=\"" . $area_href . "\"";
1178        $tag_coords        = "COORDS=\"" . $area_coords . "\"";
1179        $tag_tooltip1        = "ALT=\"" . $area_tooltip . "\"";
1180        $tag_tooltip2        = "TITLE=\"" . $area_tooltip . "\"";
1181
1182        return ("<AREA SHAPE=\"RECT\" " . $tag_coords . " " . $tag_href . " " . $tag_tooltip1 . " " . $tag_tooltip2 . ">");
1183    }
1184
1185    function colorHex( $color )
1186    {
1187        $my_color = imageColorAllocate( $this->image, hexdec( substr( $color, 0, 2 )), hexdec( substr( $color, 2, 2 )), hexdec( substr( $color, 4, 2 )) );
1188
1189        return $my_color;
1190    }
1191
1192    function setLoad( $load )
1193    {
1194        $this->load = $load;
1195    }
1196
1197    function setHostname( $hostname )
1198    {
1199        $this->hostname = $hostname;
1200    }
1201
1202    function getHostname()
1203    {
1204        return $this->hostname;
1205    }
1206
1207    function getJobs()
1208    {
1209        return $this->jobs;
1210    }
1211
1212    function setShowinfo( $showinfo )
1213    {
1214        $this->showinfo = $showinfo;
1215    }
1216
1217    function drawSmall()
1218    {
1219        global $SMALL_CLUSTERIMAGE_NODEWIDTH;
1220
1221        $this->size    = $SMALL_CLUSTERIMAGE_NODEWIDTH;
1222
1223        $this->draw();
1224    }
1225
1226    function drawBig()
1227    {
1228        global $BIG_CLUSTERIMAGE_NODEWIDTH;
1229
1230        $this->size    = $BIG_CLUSTERIMAGE_NODEWIDTH;
1231
1232        $this->draw();
1233    }
1234
1235    function draw()
1236    {
1237        global $JOB_NODE_MARKING, $NODE_DOWN_MARKING, $NODE_OFFLINE_MARKING;
1238
1239        $black_color = imageColorAllocate( $this->image, 0, 0, 0 );
1240        $size = $this->size;
1241
1242        imageFilledRectangle( $this->image, $this->x, $this->y, $this->x+($size), $this->y+($size), $black_color );
1243
1244        if( $this->showinfo)
1245        {
1246            $this->load = $this->determineLoad();
1247
1248            if( !isset( $this->image ) or !isset( $this->x ) or !isset( $this->y ) )
1249            {
1250                printf( "aborting\n" );
1251                printf( "x %d y %d load %f\n", $this->x, $this->y, $load );
1252                return;
1253            }
1254
1255            // Convert Ganglias Hexadecimal load color to a Decimal one
1256            //
1257            $load = $this->determineLoad();   
1258            $usecolor = $this->colorHex( load_color($load) );
1259            imageFilledRectangle( $this->image, $this->x+1, $this->y+1, $this->x+($size-1), $this->y+($size-1), $usecolor );
1260            if( $this->down )
1261            {
1262                imageString( $this->image, 1, $this->x+(($size/2)-1), $this->y+(($size/2)-4), $NODE_DOWN_MARKING, $black_color );
1263            }
1264            else if( $this->offline )
1265            {
1266                imageString( $this->image, 1, $this->x+(($size/2)-1), $this->y+(($size/2)-4), $NODE_OFFLINE_MARKING, $black_color );
1267            }
1268            else if( count( $this->jobs ) > 0 )
1269            {
1270                imageString( $this->image, 1, $this->x+(($size/2)-1), $this->y+(($size/2)-4), $JOB_NODE_MARKING, $black_color );
1271            }
1272        }
1273        else
1274        {
1275            // White
1276            $usecolor = imageColorAllocate( $this->image, 255, 255, 255 );
1277            imageFilledRectangle( $this->image, $this->x+1, $this->y+1, $this->x+($size-1), $this->y+($size-1), $usecolor );
1278        }
1279    }
1280
1281    function determineLoad()
1282    {
1283        global $metrics;
1284
1285        $cpus = $metrics[$this->hostname]['cpu_num']['VAL'];
1286        if (!$cpus)
1287        {
1288            $cpus=1;
1289        }
1290
1291        $load_one    = $metrics[$this->hostname]['load_one']['VAL'];
1292        $load        = ((float) $load_one)/$cpus;
1293
1294        return $load;
1295    }
1296}
1297
1298class ClusterImage
1299{
1300    var $dataget, $image, $clustername;
1301    var $filtername, $filters;
1302
1303    function ClusterImage( $data, $clustername )
1304    {
1305        $this->dataget        = new DataGatherer( $clustername );
1306        $this->data        = $data;
1307        $this->clustername    = $clustername;
1308        $this->filters        = array();
1309        $this->size        = 's';
1310        $this->width        = 0;
1311        $this->height        = 0;
1312        $this->output        = 1;
1313        $this->jobs         = null;
1314        $this->nodes        = null;
1315    }
1316
1317    function getWidth()
1318    {
1319        return $this->width;
1320    }
1321    function getHeight()
1322    {
1323        return $this->height;
1324    }
1325    function setSmall()
1326    {
1327        $this->size    = 's';
1328    }
1329    function setBig()
1330    {
1331        $this->size    = 'b';
1332    }
1333    function setNoimage()
1334    {
1335        $this->output    = 0;
1336    }
1337    function setJobs($jobs )
1338    {
1339        $this->jobs     = &$jobs;
1340    }
1341    function getJobs()
1342    {
1343        if( $this->jobs == null )
1344        {
1345            $mydatag = $this->dataget;
1346            $mydatag->parseXML( $this->data );
1347            $this->jobs = $mydatag->getJobs();
1348        }
1349
1350        return $this->jobs;
1351    }
1352    function getNodes()
1353    {
1354        if( $this->nodes== null )
1355        {
1356            $mydatag = $this->dataget;
1357            $mydatag->parseXML( $this->data );
1358            $this->nodes = $mydatag->getNodes();
1359        }
1360
1361        return $this->nodes;
1362    }
1363    function setNodes($nodes)
1364    {
1365        $this->nodes    = &$nodes;
1366    }
1367    function isSmall()
1368    {
1369        return ($this->size == 's');
1370    }
1371    function isBig()
1372    {
1373        return ($this->size == 'b');
1374    }
1375    function setFilter( $filtername, $filtervalue )
1376    {
1377        $this->filters[$filtername] = $filtervalue;
1378    }
1379
1380    function filterNodes( $jobs, $nodes )
1381    {
1382        $filtered_nodes = array();
1383
1384        //print_r( $nodes );
1385
1386        foreach( $nodes as $node )
1387        {
1388            $hostname = $node->getHostname();
1389
1390            $addhost = 1;
1391
1392            if( count( $this->filters ) > 0 )
1393            {
1394                $mynjobs = $node->getJobs();
1395
1396                if( count( $mynjobs ) > 0 )
1397                {
1398                    foreach( $mynjobs as $myjob )
1399                    {
1400                        foreach( $this->filters as $filtername => $filtervalue )
1401                        {
1402                            if( $filtername!=null && $filtername!='' )
1403                            {
1404                                if( $filtername == 'jobid' && !$node->hasJob( $filtervalue) )
1405                                {
1406                                    $addhost = 0;
1407                                }
1408                                else if( $filtername != 'jobid' )
1409                                {
1410                                    if( $jobs[$myjob][$filtername] != $filtervalue )
1411                                    {
1412                                        $addhost = 0;
1413                                    }
1414                                }
1415                            }
1416                        }
1417                    }
1418                }
1419                else
1420                {
1421                    $addhost = 0;
1422                }
1423            }
1424
1425            if( $addhost )
1426            {
1427                $filtered_nodes[] = $hostname;
1428            }
1429        }
1430
1431        return $filtered_nodes;
1432    }
1433
1434    function draw()
1435    {
1436        global $SMALL_CLUSTERIMAGE_MAXWIDTH, $SMALL_CLUSTERIMAGE_NODEWIDTH;
1437        global $BIG_CLUSTERIMAGE_MAXWIDTH, $BIG_CLUSTERIMAGE_NODEWIDTH;
1438        global $CLUSTER_CONFS, $confcluster, $SHOW_EMPTY_COLUMN, $SHOW_EMPTY_ROW;
1439
1440        global $SORTBY_HOSTNAME, $SORT_ORDER, $skan_str;
1441        global $x_first, $y_first;
1442
1443        foreach( $CLUSTER_CONFS as $confcluster => $conffile )
1444        {
1445            if( strtolower( trim($this->clustername) ) == strtolower(trim($confcluster)) )
1446            {
1447                include_once $conffile;
1448            }
1449        }
1450
1451        if( $this->isSmall() )
1452        {
1453            $max_width    = $SMALL_CLUSTERIMAGE_MAXWIDTH;
1454            $node_width    = $SMALL_CLUSTERIMAGE_NODEWIDTH;
1455        }
1456        else if( $this->isBig() )
1457        {
1458            $max_width    = $BIG_CLUSTERIMAGE_MAXWIDTH;
1459            $node_width    = $BIG_CLUSTERIMAGE_NODEWIDTH;
1460        }
1461
1462        $nodes        = $this->getNodes();
1463        $nodes_hosts    = array_keys( $nodes );
1464
1465        $nodes_nr    = count( $nodes );
1466
1467        $nodes_size    = $nodes_nr*$node_width;
1468        $node_rows    = 0;
1469
1470        if( $nodes_size > $max_width )
1471        {
1472            $nodes_per_row = ( (int) ($max_width/$node_width) );
1473        }
1474        else
1475        {
1476            $nodes_per_row = $nodes_size;
1477            $node_rows = 1;
1478        }
1479
1480        if( $nodes_per_row < $nodes_nr )
1481        {
1482            $node_rows = ( (int) ($nodes_nr/$nodes_per_row) );
1483            $node_rest = fmod( $nodes_nr, $nodes_per_row );
1484
1485            if( $node_rest > 0 )
1486            {
1487                $node_rows++;
1488            }
1489        }
1490
1491        $y_offset    = 0;
1492        $font         = 2;
1493        $fontwidth    = ImageFontWidth( $font );
1494        $fontheight    = ImageFontHeight( $font );
1495        $fontspaceing    = 2;
1496        $y_offset    = $fontheight + (2 * $fontspaceing);
1497
1498        $this->width    = $max_width;
1499        $this->height    = ($y_offset + (($node_rows*$node_width)+1) );
1500
1501        $jobs = $this->getJobs();
1502        $filtered_nodes = $this->filterNodes( $jobs, $nodes );
1503
1504        if( $SORTBY_HOSTNAME != "" )
1505        {
1506                $sorted     = array();
1507
1508            $x_first    = 0;
1509            $y_first    = 0;
1510
1511            $skan_str    = $SORTBY_HOSTNAME;
1512
1513            global $x_present, $y_present;
1514            $x_present    = false;
1515            $y_present    = false;
1516
1517            // Should we scan by X, Y or both
1518            //
1519            if(strpos( $SORTBY_HOSTNAME, "{x}" ) != false )
1520            {
1521                $x_str        = "{x}";
1522                $x_present    = true;
1523            }
1524            else if(strpos( $SORTBY_HOSTNAME, "{X}" ) != false )
1525            {
1526                $x_str        = "{X}";
1527                $x_present    = true;
1528            }
1529            if(strpos( $SORTBY_HOSTNAME, "{y}" ) != false )
1530            {
1531                $y_str        = "{y}";
1532                $y_present    = true;
1533            }
1534            else if(strpos( $SORTBY_HOSTNAME, "{Y}" ) != false )
1535            {
1536                $y_str        = "{Y}";
1537                $y_present    = true;
1538            }
1539
1540            // If we should scan for both X and Y: see which one is first
1541            //
1542            if(( strpos( $SORTBY_HOSTNAME, $x_str ) < strpos( $SORTBY_HOSTNAME, $y_str ) ) && ( $x_present && $y_present ))
1543            {
1544                $x_first    = 1;
1545            }
1546            else if(( strpos( $SORTBY_HOSTNAME, $x_str ) > strpos( $SORTBY_HOSTNAME, $y_str ) ) && ( $x_present && $y_present ))
1547            {
1548                $y_first    = 1;
1549       
1550            }
1551            else if( $x_present )
1552            {
1553                $x_first    = 1;
1554            }
1555            else if( $y_present )
1556            {
1557                $y_first    = 1;
1558            }
1559
1560            // Now replace our {x} and {y} with %d for sscanf parsing
1561            //
1562            if(( $x_first ) && ( $x_present && $y_present ) )
1563            {
1564                $skan_str    = str_replace( $x_str, "%d", $skan_str );
1565                $skan_str    = str_replace( $y_str, "%d", $skan_str );
1566            } 
1567            else if( $x_present)
1568            {
1569                $skan_str    = str_replace( $x_str, "%d", $skan_str );
1570            }
1571            else if( $y_present)
1572            {
1573                $skan_str    = str_replace( $y_str, "%d", $skan_str );
1574            }
1575
1576            $x_min        = null;
1577            $x_max        = null;
1578            $y_min        = null;
1579            $y_max        = null;
1580
1581            $x_columns    = array();
1582            $y_rows        = array();
1583
1584            // Now let's walk through all our nodes and see which one are valid for our scan pattern
1585            //
1586            foreach( $nodes as $hostname => $node )
1587            {
1588                $x    = null;
1589                $y    = null;
1590
1591                if( $x_present && $y_present )
1592                {
1593                    if( $x_first )
1594                    {
1595                        $n = sscanf( $hostname, $skan_str, $x, $y );
1596                    }
1597                    else if( $y_first )
1598                    {
1599                        $n = sscanf( $hostname, $skan_str, $y, $x );
1600                    }
1601
1602                    // Remove nodes that don't match
1603                    //
1604                    if( $n < 2 )
1605                    {
1606                        // This node hostname has no match for: {x} and {y}
1607                        //
1608                        unset( $nodes[$hostname] );
1609                    }
1610                }
1611                else if( $x_present && !$y_present )
1612                {
1613                    $n = sscanf( $hostname, $skan_str, $x );
1614
1615                    // Remove nodes that don't match
1616                    //
1617                    if( $n < 1 )
1618                    {
1619                        // This node hostname has no match for: {x}
1620                        //
1621                        unset( $nodes[$hostname] );
1622                    }
1623                    $y    = 1;
1624                }
1625                else if( $y_present && !$x_present )
1626                {
1627                    $n = sscanf( $hostname, $skan_str, $y );
1628
1629                    // Remove nodes that don't match
1630                    //
1631                    if( $n < 1 )
1632                    {
1633                        // This node hostname has no match for: {y}
1634                        //
1635                        unset( $nodes[$hostname] );
1636                    }
1637                    $x    = 1;
1638                }
1639
1640                // Determine the lowest value of {x} that exists in all node hostnames
1641                //
1642                if( !$x_min && $x != null )
1643                {
1644                    $x_min    = $x;
1645                }
1646                else if( $x < $x_min && $x != null )
1647                {
1648                    $x_min    = $x;
1649                }
1650
1651                // Determine the highest value of {x} that exists in all node hostnames
1652                //
1653                if( !$x_max && $x != null )
1654                {
1655                    $x_max    = $x;
1656                }
1657                else if( $x > $x_max && $x != null )
1658                {
1659                    $x_max    = $x;
1660                }
1661
1662                // Determine the lowest value of {y} that exists in all node hostnames
1663                //
1664                if( !$y_min && $y != null )
1665                {
1666                    $y_min    = $y;
1667                }
1668                else if( $y < $y_min && $y != null )
1669                {
1670                    $y_min    = $y;
1671                }
1672
1673                // Determine the highest value of {y} that exists in all node hostnames
1674                //
1675                if( !$y_max && $y != null )
1676                {
1677                    $y_max    = $y;
1678                }
1679                else if( $y > $y_max && $y != null )
1680                {
1681                    $y_max    = $y;
1682                }
1683
1684                // Store which non-empty columns and rows we found
1685                //
1686                if( !in_array( $x, $x_columns ) )
1687                {
1688                    $x_columns[] = $x;
1689                }
1690                if( !in_array( $y, $y_rows ) )
1691                {
1692                    $y_rows[] = $y;
1693                }
1694            }
1695
1696            // Sort all the nodes (alpha and numerically)
1697            // 1: gb-r1n1, 2: gb-r1n2, 3: gb-r2n1, etc
1698            //
1699            $sorted_nodes    = usort( $nodes, "cmp" );
1700
1701            //print_r( $x_columns ) ;
1702
1703            $cur_node    = 0;
1704
1705            $x_offset    = 0;
1706            $y_offset    = 0;
1707            $font         = 2;
1708            $fontwidth    = ImageFontWidth( $font );
1709            $fontheight    = ImageFontHeight( $font );
1710            $fontspaceing    = 2;
1711
1712            if( $this->isSmall() ) 
1713            {
1714                $y_offset    = $y_offset + (2 * $fontspaceing) + $fontheight;
1715            }
1716
1717            if( $this->isBig() ) 
1718            {
1719                $y_offset    = ($fontheight * (1 + strlen( $x_max) ) ) + ((2 + strlen( $x_max)) * $fontspaceing);
1720                $x_offset    = ($fontwidth * (1 + strlen( $y_max) ) ) + ((2 + strlen( $y_max)) * $fontspaceing);
1721            }
1722
1723            $image_width    = $x_offset + ($node_width * ($x_max-$x_min+2));
1724
1725            if( $this->isSmall() ) 
1726            {
1727                $image_width    = $max_width;
1728            }
1729            else if( $this->isBig() ) 
1730            {
1731                $image_width    = ($image_width < $max_width) ? $image_width : $max_width;
1732            }
1733            $image_height    = $y_offset + ($node_width * ($y_max-$y_min+2));
1734
1735            $this->width    = $image_width;
1736            $this->heigth    = $image_heigth;
1737
1738            $image        = imageCreateTrueColor( $image_width, $image_height );
1739            $colorwhite    = imageColorAllocate( $image, 255, 255, 255 );
1740
1741            imageFill( $image, 0, 0, $colorwhite );
1742
1743            if( $this->isSmall() )
1744            {
1745                // Draw a fancy little header text to explain what it is
1746                //
1747                $colorblue    = imageColorAllocate( $image, 0, 0, 255 );
1748
1749                imageString( $image, $font, 2, 2, "Monarch Joblist - cluster: ".$this->clustername, $colorblue );
1750            }
1751
1752            if( $this->isBig() && ( isset( $SORT_XLABEL ) || isset( $SORT_YLABEL ) ) )
1753            {
1754                $colorblue    = imageColorAllocate( $image, 0, 0, 255 );
1755
1756                if( isset( $SORT_XLABEL ) )
1757                {
1758                    // Print the {x} label: rack
1759                    //
1760                    imageString( $image, $font, $x_offset, $fontspaceing, $SORT_XLABEL, $colorblue );
1761                }
1762
1763                if( isset( $SORT_YLABEL ) )
1764                {
1765                    // Stupid php without imageStringDown function... we'll make one ourself
1766                    //
1767
1768                    // Print the {y} label: node
1769                    //
1770                    imageStringDown( $image, $font, $fontspaceing, $y_offset, $SORT_YLABEL, $colorblue );
1771                }
1772            }
1773
1774            $previous_n    = 0;
1775            $previous_m    = 0;
1776            $x_empty_count    = 0;
1777            $y_empty_count    = 0;
1778
1779            // Let's start assigning x,y coordinates now
1780            //
1781            for( $n = $x_min; $n <= $x_max; $n++ )
1782            {
1783                for( $m = $y_min; $m <= $y_max; $m++ )
1784                {
1785                    if( $x_min > 0 )
1786                    {
1787                        $x    = $x_offset + ( ($n-$x_min) * $node_width ) - ($x_empty_count * $node_width);
1788                    }
1789                    if( $y_min > 0 )
1790                    {
1791                        $y    = $y_offset + ( ($m-$y_min) * $node_width ) - ($y_empty_count * $node_width);
1792                    }
1793
1794                    // Don't show empty rows/columns if option enabled
1795                    //
1796                    if( !in_array( $n, $x_columns ) && !$SHOW_EMPTY_COLUMN )
1797                    {
1798                        // Skip to next iteration: we don't want a empty column
1799                        //
1800                        if( $n > $previous_n )
1801                        {
1802                            $previous_n = $n;
1803                            $x_empty_count++;
1804                        }
1805                        continue;
1806                    }
1807                    if( !in_array( $m, $y_rows ) && !$SHOW_EMPTY_ROW )
1808
1809                    {
1810                        // Skip to next iteration: we don't want a empty column
1811                        //
1812                        if( $m > $previous_m )
1813                        {
1814                            $previous_m = $m;
1815                            $y_empty_count++;
1816                        }
1817                        continue;
1818                    }
1819
1820                    if( $this->isBig() ) 
1821                    {
1822                        // Draw y(node) column number header
1823                        //
1824                        if(( $n == $x_min ) && ( isset($SORT_YLABEL) ) )
1825                        {
1826                            $mfontspacing    = 1;
1827
1828                            $ylabel_x    = $x - ( $fontwidth * strlen( $y_max ) ) - $mfontspacing;
1829                            $ylabel_y    = $y;
1830
1831                            imageString( $image, $font, $ylabel_x, $ylabel_y, strval( $m ), $colorblue );
1832
1833                            $xmin_hit[$n]    = true;
1834                        }
1835
1836                        // Draw x(rack) column number header
1837                        //
1838                        if(( $m == $y_min ) && ( isset($SORT_XLABEL) ) )
1839                        {
1840                            $mfontspacing    = 2;
1841                            $xlabel_y    = $y - ( $fontheight * strlen( $x_max ) );
1842                            $xlabel_x    = $x + $mfontspacing; 
1843
1844                            imageStringDown( $image, $font, $xlabel_x, $xlabel_y, strval( $n ), $colorblue );
1845                        }
1846                    }
1847
1848                    if( isset( $nodes[$cur_node] ) ) 
1849                    {
1850                        $host    = $nodes[$cur_node]->getHostname();
1851
1852                        if( $x_present && $y_present )
1853                        {
1854                            if( $x_first )
1855                            {
1856                                $nn = sscanf( $host, $skan_str, $rx, $ry );
1857                            }
1858                            else if( $y_first )
1859                            {
1860                                $nn = sscanf( $host, $skan_str, $ry, $rx );
1861                            }
1862                            if ( $nn < 2 )
1863                            {
1864                                //printf( "skipping node %s - y present & x present + <2 x,y matchs\n", $host);
1865                                continue;
1866                            }
1867                            if( intval( $rx ) > $n )
1868                            {
1869                                // If x(rack) is higher than current x, skip to next x(rack)
1870                                //
1871                                $m        = $y_max + 1;
1872
1873                                continue;
1874                            }
1875                            if( intval( $ry ) > $m )
1876                            {
1877                                // If y(node) is higher than current y, skip to next y(node)
1878                                //
1879                                continue;
1880                            }
1881                        }
1882                        else if( $x_present )
1883                        {
1884                            $nn = sscanf( $host, $skan_str, $rx );
1885                        }
1886                        else if( $y_present )
1887                        {
1888                            $nn = sscanf( $host, $skan_str, $ry );
1889                        }
1890
1891                        if( !in_array( $host, $filtered_nodes ) )
1892                        {
1893                            // This node has been filtered out: we only want to see certain nodes
1894                            //
1895                            $nodes[$cur_node]->setShowinfo( 0 );
1896                        }
1897
1898                        $nodes[$cur_node]->setCoords( $x, $y );
1899                        $nodes[$cur_node]->setImage( $image );
1900
1901                        if( $this->isSmall() )
1902                        {
1903                            $nodes[$cur_node]->drawSmall();
1904                        }
1905                        else if( $this->isBig() )
1906                        {
1907                            $nodes[$cur_node]->drawBig();
1908                        }
1909
1910                        $cur_node++;
1911                    }
1912                }
1913            }
1914
1915        }
1916        else
1917        {
1918            if( $this->isSmall() )
1919            {
1920                $image        = imageCreateTrueColor( $max_width, ($y_offset + (($node_rows*$node_width)+1) ) );
1921            }
1922            else if( $this->isBig() )
1923            {
1924                $image_width    = ($node_width * $nodes_nr) + 2;
1925                $image_width    = ($image_width < $max_width) ? $image_width : $max_width;
1926                $image        = imageCreateTrueColor( $image_width, ($y_offset + (($node_rows*$node_width)+1) ) );
1927            }
1928            $colorwhite    = imageColorAllocate( $image, 255, 255, 255 );
1929
1930            imageFill( $image, 0, 0, $colorwhite );
1931
1932            if( $this->isSmall() )
1933            {
1934                $colorblue    = imageColorAllocate( $image, 0, 0, 255 );
1935
1936                imageString( $image, $font, 2, 2, "Monarch Joblist - cluster: ".$this->clustername, $colorblue );
1937            }
1938
1939            for( $n = 0; $n < $node_rows; $n++ )
1940            {
1941                for( $m = 0; $m < $nodes_per_row; $m++ )
1942                {
1943                    $x = ($m * $node_width);
1944                    $y = $y_offset + ($n * $node_width);
1945
1946                    $cur_node = ($n * $nodes_per_row) + ($m);
1947                    $host = isset( $nodes_hosts[$cur_node] ) ? $nodes_hosts[$cur_node] : '';
1948
1949                    if( isset( $nodes[$host] ) )
1950                    {
1951                        $nodes[$host]->setCoords( $x, $y );
1952                        $nodes[$host]->setImage( $image );
1953
1954                        if( !in_array( $host, $filtered_nodes ) )
1955                        {
1956                            $nodes[$host]->setShowinfo( 0 );
1957                        }
1958
1959                        if( $this->isSmall() )
1960                        {
1961                            $nodes[$host]->drawSmall();
1962                        }
1963                        else if( $this->isBig() )
1964                        {
1965                            $nodes[$host]->drawBig();
1966                        }
1967                    }
1968                }
1969            }
1970        }
1971   
1972        $this->nodes    = &$nodes;
1973
1974        if ($this->output)
1975        {
1976            header( 'Content-type: image/png' );
1977            imagePNG( $image );
1978            imageDestroy( $image );
1979        }
1980    }
1981
1982    function getImagemapArea()
1983    {
1984        $clusterimage_map    = "";
1985
1986        foreach( $this->nodes as $hostname => $node )
1987        {
1988            $node_map        = $node->getImagemapArea();
1989            $clusterimage_map    .= $node_map;
1990        }
1991
1992        return $clusterimage_map;
1993    }
1994}
1995
1996class EmptyImage
1997{
1998    function draw()
1999    {
2000        $image        = imageCreateTrueColor( 1, 1 );
2001        $colorwhite    = imageColorAllocate( $image, 255, 255, 255 );
2002        imageFill( $image, 0, 0, $colorwhite );                         
2003
2004        header( 'Content-type: image/png' );
2005        imagePNG( $image );
2006        imageDestroy( $image );
2007    }
2008}
2009
2010class HostImage
2011{
2012    var $data_gather, $cluster, $host, $node, $image;
2013    var $headerstrlen;
2014
2015    function HostImage( $data_gather, $cluster, $host )
2016    {
2017        $this->data_gather     = $data_gather;
2018        $this->cluster        = $cluster;
2019        $this->host        = $host;
2020        $this->y_offset        = 0;
2021        $this->font        = 2;
2022        $this->fontspaceing    = 2;
2023        $this->headerstrlen    = array();
2024
2025        $this->fontheight    = ImageFontHeight( $this->font );
2026        $this->fontwidth    = ImageFontWidth( $this->font );
2027
2028        $dg            = &$this->data_gather;
2029        $this->node        = &$dg->getNode( $this->host );
2030        $n            = &$this->node;
2031        $this->njobs        = $n->getJobs();
2032    }
2033
2034    function drawJobs()
2035    {
2036        $dg                     = &$this->data_gather;
2037        $colorblack        = imageColorAllocate( $this->image, 0, 0, 0 );
2038
2039        for( $n = 0; $n < count( $this->njobs ); $n++ )
2040        {
2041            $jobid            = $this->njobs[$n];
2042            $jobinfo        = $dg->getJob( $jobid );
2043
2044            $xoffset        = 5;
2045            imageString( $this->image, $this->font, $xoffset, $this->y_offset, strval( $jobid ), $colorblack );
2046
2047            foreach( $this->headerstrlen as $headername => $headerlen )
2048            {
2049                if( $headername == 'nodes' )
2050                {
2051                    $attrval    = strval( count( $jobinfo['nodes'] ) );
2052                }
2053                else if( $headername == 'cpus' )
2054                {
2055                    if( !isset( $jobinfo['ppn'] ) )
2056                    {
2057                        $jobinfo['ppn'] = 1;
2058                    }
2059
2060                    $attrval    = strval( count( $jobinfo['nodes'] ) * intval( $jobinfo['ppn'] ) );
2061                }
2062                else if( $headername == 'runningtime' )
2063                {
2064                    $attrval    = makeTime( intval( $jobinfo['reported'] ) - intval( $jobinfo['start_timestamp'] ) );
2065                }
2066                else
2067                {
2068                    $attrval    = strval( $jobinfo[$headername] );
2069                }
2070
2071                imageString( $this->image, $this->font, $xoffset, $this->y_offset, $attrval, $colorblack );
2072       
2073                $xoffset    = $xoffset + ($this->fontwidth * ( $headerlen + 1 ) );
2074            }
2075           
2076            $this->newLineOffset();
2077        }
2078    }
2079
2080    function drawHeader()
2081    {
2082        $dg                     = &$this->data_gather;
2083
2084        for( $n = 0; $n < count( $this->njobs ); $n++ )
2085        {
2086            $jobid            = $this->njobs[$n];
2087            $jobinfo        = $dg->getJob( $jobid );
2088
2089            if( !isset( $this->headerstrlen['id'] ) )
2090            {
2091                $this->headerstrlen['id']    = strlen( strval( $jobid ) );
2092            }
2093            else if( strlen( strval( $jobid ) ) > $this->headerstrlen['id'] )
2094            {
2095                $this->headerstrlen['id']    = strlen( strval( $jobid ) );
2096            }
2097
2098            if( !isset( $this->headerstrlen['owner'] ) )
2099            {
2100                $this->headerstrlen['owner']    = strlen( strval( $jobinfo['owner'] ) );
2101            }
2102            else if( strlen( strval( $jobinfo['owner'] ) ) > $this->headerstrlen['owner'] )
2103            {
2104                $this->headerstrlen['owner']    = strlen( strval( $jobinfo['owner'] ) );
2105            }
2106
2107            if( !isset( $this->headerstrlen['queue'] ) )
2108            {
2109                $this->headerstrlen['queue']    = strlen( strval( $jobinfo['queue'] ) );
2110            }
2111            else if( strlen( strval( $jobinfo['queue'] ) ) > $this->headerstrlen['queue'] )
2112            {
2113                $this->headerstrlen['queue']    = strlen( strval( $jobinfo['queue'] ) );
2114            }
2115
2116            if( !isset( $jobinfo['ppn'] ) )
2117            {
2118                $jobinfo['ppn'] = 1;
2119            }
2120
2121            $cpus            = count( $jobinfo['nodes'] ) * intval( $jobinfo['ppn'] );
2122
2123            if( !isset( $this->headerstrlen['cpus'] ) )
2124            {
2125                $this->headerstrlen['cpus']    = strlen( strval( $cpus ) );
2126            }
2127            else if( strlen( strval( $cpus ) ) > $this->headerstrlen['cpus'] )
2128            {
2129                $this->headerstrlen['cpus']    = strlen( strval( $cpus ) );
2130            }
2131
2132            $nodes            = count( $jobinfo['nodes'] );
2133
2134            if( !isset( $this->headerstrlen['nodes'] ) )
2135            {
2136                $this->headerstrlen['nodes']    = strlen( strval( $nodes ) );
2137            }
2138            else if( strlen( strval( $nodes) ) > $this->headerstrlen['nodes'] )
2139            {
2140                $this->headerstrlen['nodes']    = strlen( strval( $nodes ) );
2141            }
2142
2143            $runningtime        = makeTime( intval( $jobinfo[reported] ) - intval( $jobinfo['start_timestamp'] ) );
2144
2145            if( !isset( $this->headerstrlen['runningtime'] ) )
2146            {
2147                $this->headerstrlen['runningtime']    = strlen( strval( $runningtime) );
2148            }
2149            else if( strlen( strval( $runningtime) ) > $this->headerstrlen['runningtime'] )
2150            {
2151                $this->headerstrlen['runningtime']    = strlen( strval( $runningtime) );
2152            }
2153
2154            if( !isset( $this->headerstrlen['name'] ) )
2155            {
2156                $this->headerstrlen['name']    = strlen( strval( $jobinfo['name'] ) );
2157            }
2158            else if( strlen( strval( $jobinfo['name'] ) ) > $this->headerstrlen['name'] )
2159            {
2160                $this->headerstrlen['name']    = strlen( strval( $jobinfo['name'] ) );
2161            }
2162        }
2163
2164        $xoffset    = 5;
2165
2166        foreach( $this->headerstrlen as $headername => $headerlen )
2167        {
2168            $colorgreen    = imageColorAllocate( $this->image, 0, 200, 0 );
2169
2170            if( $headerlen < strlen( $headername ) )
2171            {
2172                $this->headerstrlen[$headername]    = strlen( $headername );
2173            }
2174
2175            imageString( $this->image, $this->font, $xoffset, $this->y_offset, ucfirst( $headername ), $colorgreen );
2176
2177            $xoffset    = $xoffset + ($this->fontwidth * ( $this->headerstrlen[$headername] + 1 ) );
2178        }
2179        $this->newLineOffset();
2180    }
2181
2182    function newLineOffset()
2183    {
2184        $this->y_offset        = $this->y_offset + $this->fontheight + $this->fontspaceing;
2185    }
2186
2187    function draw()
2188    {
2189        $xlen        = 450;
2190        $ylen        = ( count( $this->njobs ) * ( $this->fontheight + $this->fontspaceing ) ) + (3 * $this->fontheight);
2191
2192        $this->image    = imageCreateTrueColor( $xlen, $ylen );
2193        $colorwhite    = imageColorAllocate( $this->image, 255, 255, 255 );
2194        imageFill( $this->image, 0, 0, $colorwhite );                         
2195
2196        $colorblue    = imageColorAllocate( $this->image, 0, 0, 255 );
2197
2198        imageString( $this->image, $this->font, 1, $this->y_offset, "Monarch Joblist - host: ".$this->host, $colorblue );
2199        $this->newLineOffset();
2200
2201        $this->drawHeader();
2202        $this->drawJobs();
2203
2204        header( 'Content-type: image/png' );
2205        imagePNG( $this->image );
2206        imageDestroy( $this->image );
2207    }
2208}
2209
2210function imageStringDown( &$image, $font, $x, $y, &$s, &$col )
2211{
2212    $fw    = imagefontwidth( $font);
2213    $fh    = imagefontheight( $font);
2214   
2215    $fontspacing = 0;
2216
2217    $fx    = $x;
2218    $fy    = $y;
2219
2220    for( $n=0; $n<strlen( $s ); $n++ )
2221    {
2222        $myc    = $s{$n};
2223
2224        imagestring( $image, $font, $fx, $fy, $myc, $col );
2225
2226        $fy    += ($fontspacing + $fh );
2227    }
2228}
2229
2230function array_rem( $val, &$arr )
2231{
2232    // Delete val from arr
2233    //
2234    $i    = array_search( $val, $arr );
2235
2236    if( $i == false ) return false;
2237
2238    $arr    = array_merge( array_slice( $arr, 0, $i ), array_slice( $arr, $i+1, count( $arr ) ) );
2239
2240    return true;
2241}
2242
2243function cmp( $a, $b ) 
2244{
2245    global $SORT_ORDER;
2246    global $skan_str;
2247    global $x_first, $y_first;
2248    global $x_present, $y_present;
2249
2250    $a_node        = $a;
2251    $b_node        = $b;
2252    $a        = $a_node->getHostname();
2253    $b        = $b_node->getHostname();
2254
2255    if( $a == $b ) return 0;
2256
2257    $a_x        = 0;
2258    $b_x        = 0;
2259    $a_y        = 0;
2260    $b_y        = 0;
2261
2262    if( $x_present && $y_present )
2263    {
2264        if( $x_first )
2265        {
2266            $n = sscanf( $a, $skan_str, $a_x, $a_y );
2267            $n = sscanf( $b, $skan_str, $b_x, $b_y );
2268        }
2269        else if( $y_first )
2270        {
2271            $n = sscanf( $a, $skan_str, $a_y, $a_x );
2272            $n = sscanf( $b, $skan_str, $b_y, $b_x );
2273        }
2274    } 
2275    else if( $x_present && !$y_present )
2276    {
2277        $n = sscanf( $a, $skan_str, $a_x );
2278        $n = sscanf( $b, $skan_str, $b_x );
2279    }
2280    else if( $y_present && !$x_present )
2281    {
2282        $n = sscanf( $a, $skan_str, $a_y );
2283        $n = sscanf( $b, $skan_str, $b_y );
2284    }
2285
2286    if ( $SORT_ORDER=="desc" )
2287    {
2288
2289        if( $x_present && $y_present )
2290        {
2291            // 1  = a < b
2292            // -1 = a > b
2293            //
2294            if ($a_x == $b_x)
2295            {
2296                if ($a_y < $b_y)
2297                {
2298                    return 1;
2299                }
2300                else if ($a_y > $b_y)
2301                {
2302                    return -1;
2303                }
2304            }
2305            else if ($a_x < $b_x)
2306            {
2307                return 1;
2308            }
2309            else if ($a_x > $b_x)
2310            {
2311                return -1;
2312            }
2313        } 
2314        else if( $x_present && !$y_present )
2315        {
2316            if ($a_x < $b_x)
2317            {
2318                return 1;
2319            }
2320            else if ($a_x > $b_x)
2321            {
2322                return -1;
2323            }
2324        }
2325        else if( $y_present && !$x_present )
2326        {
2327            if ($a_y < $b_y)
2328            {
2329                return 1;
2330            }
2331            else if ($a_y > $b_y)
2332            {
2333                return -1;
2334            }
2335        }
2336    }
2337    else if ( $SORT_ORDER == "asc" )
2338    {
2339
2340        if( $x_present && $y_present )
2341        {
2342            // 1  = a > b
2343            // -1 = a < b
2344            //
2345            if ($a_x == $b_x)
2346            {
2347                if ($a_y > $b_y)
2348                {
2349                    return 1;
2350                }
2351                else if ($a_y < $b_y)
2352                {
2353                    return -1;
2354                }
2355            }
2356            else if ($a_x > $b_x)
2357            {
2358                return 1;
2359            }
2360            else if ($a_x < $b_x)
2361            {
2362                return -1;
2363            }
2364        }
2365        else if( $x_present && !$y_present )
2366        {
2367            if ($a_x > $b_x)
2368            {
2369                return 1;
2370            }
2371            else if ($a_x < $b_x)
2372            {
2373                return -1;
2374            }
2375        }
2376        else if( $y_present && !$x_present )
2377        {
2378            if ($a_y > $b_y)
2379            {
2380                return 1;
2381            }
2382            else if ($a_y < $b_y)
2383            {
2384                return -1;
2385            }
2386        }
2387    }
2388}
2389function makeTime( $time )
2390{
2391        $days = intval( $time / 86400 );
2392        $time = ($days>0) ? $time % ($days * 86400) : $time;
2393
2394        $date_str = '';
2395        $day_str = '';
2396
2397        if( $days > 0 )
2398        {
2399            if( $days > 1 )
2400            {
2401                $day_str .= $days . ' days';
2402            }
2403            else
2404            {
2405                $day_str .= $days . ' day';
2406            }
2407        }
2408
2409        $hours = intval( $time / 3600 );
2410        $time = $hours ? $time % ($hours * 3600) : $time;
2411
2412        if( $hours > 0 )
2413        {
2414             $date_str .= $hours . ':';
2415             $date_unit = 'hours'; 
2416        }
2417
2418        $minutes = intval( $time / 60 );
2419        $seconds = $minutes ? $time % ($minutes * 60) : $time;
2420
2421        if( $minutes > 0 )
2422        {
2423            if( $minutes >= 10 )
2424            {
2425                $date_str .= $minutes . ':';
2426            }
2427            else
2428            {
2429                $date_str .= '0' . $minutes . ':';
2430            }
2431                $date_unit = (!isset($date_unit)) ? 'minutes' : $date_unit;
2432        }
2433        else
2434        {
2435            if($hours > 0 )
2436            {
2437                $date_str .= '00:';
2438                $date_unit = (!isset($date_unit)) ? 'minutes' : $date_unit;
2439            }
2440        }
2441
2442        $date_unit = (!isset($date_unit)) ? 'seconds' : $date_unit;
2443
2444        if( $seconds > 0 )
2445        {
2446            if( $seconds >= 10 )
2447            {
2448                $date_str .= $seconds . ' ' . $date_unit;
2449            }
2450            else
2451            {
2452                $date_str .= '0' . $seconds . ' ' . $date_unit;
2453            }
2454        }
2455        else if ( $hours > 0 or $minutes > 0 )
2456        {
2457            $date_str .= '00 ' . $date_unit;
2458        }
2459
2460        if( $days > 0)
2461        {
2462            if( $hours > 0 or $minutes > 0 or $seconds > 0 )
2463            {
2464                $date_str = $day_str . ' - ' . $date_str;
2465            }
2466            else
2467            {
2468                $date_str = $day_str;
2469            }
2470        }
2471        return $date_str;
2472}
2473?>
Note: See TracBrowser for help on using the repository browser.