Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / mythtv / mythtv_status_ @ 8589c6df

Historique | Voir | Annoter | Télécharger (17,9 ko)

1
#!/usr/bin/perl -w
2
#
3
# Munin plugin for MythTV
4
# This plugin can graph:- Encoder Status, Days Remaining in Schedule, Job schedule, Recording Schedule, Recorded Programes, Recorded hours
5
# 
6
# Create a symbolic link to mythtv_status_{GraphType}
7
# Where {GraphType} can be encoder, epg, job,  schedule, recorded
8
# for example         mythtv_status_encoder
9
#
10
# NOTE: This plugin needs to run as root so add the following to your munin-node config file 
11
#  [mythtv_status*]
12
#  user=root
13
#  The http/xml status page must be enabled in the mythtv backend.
14
#
15
# $Log$
16
# Revision 0.1  2008/03/27  idobson
17
# Code for all options except recorded implemented 
18
#
19
# Revision 0.2  2008/03/28  idobson
20
# Tidied up the code abit/removed dead functions
21
#
22
# Revision 0.3  2008/03/28  idobson
23
# Added first attempt at getting the number of programs recorded using an sql query
24
#
25
# Revision 0.4  2008/03/29  idobson
26
# Fixed the SQL query for the recorded programs/added the number of hours recorded
27
#
28
# Revision 0.5  2008/03/29  idobson
29
# Added upcoming recordings SQL query to the schedule code
30
#
31
# Revision 0.6  2008/04/1  idobson
32
# Added a "watched recordings" to the recorded list. This is only available in MythTV ver.21
33
# Added code to read the Myth parameters (Host,SQL server,SQL user, SQL password) from the mysql.txt file
34
#
35
# Revision 0.7  2008/04/3  idobson
36
# Now using SQL to read the number of days in the EPG
37
# Changed recordings symlink to schedule, makes more sense
38
# 
39
# Revision 0.8  2008/04/6  idobson
40
# Tidied up the SQL code abit, moved it into a function.
41
#
42
# Revision 0.9  2008/04/12  idobson
43
# Added a check that we got the XML data before trying to  parse it.
44
#
45
# Revision 1.0  2008/04/15  idobson
46
# Fixed undef returned from SQL query, it now returns 0, 
47
# added error handler to SQL sub. It just dies with an error text.
48
#
49
# Revision 1.1  2008/05/03  idobson
50
# Changed unwatched to watched & changed the SQL code
51
#
52
# Revision 1.2  2008/06/13  idobson
53
# Split the EPG data up per video source
54
# Fixed afew spelling mistakes
55
#
56
# Revision 1.3  2008/06/27  idobson
57
# Tidied up the code abit. Config option only calls XMLparse and SQLsetup when required
58
# Removed unnecessary libs
59
# This should reduce the load on the munin server abit
60
#
61
#
62
# Revision 1.4  2010/10/10  idobson
63
# MythTV database information always loaded (used by autoconf,config and data dump for most options)
64
# Active tuner now split up by video source, hung encoders are listed separately
65
# Schedule now uses myth module/QUERY_GETALLPENDING to get Scheduled Recordings/Repeats/Conflicts
66
# Recorded now splits recorded into groups (Expireable, Delete pending, Save)
67
# Code now strict safe
68
#
69
# Magic markers (optional - used by munin-config and installation scripts):
70
#
71
#%# family=auto
72
#%# capabilities=autoconf
73
use DBI;
74
eval 'use MythTV; 1;'
75
    or die 'Please install MythTV';
76
use strict;
77
use warnings;
78
use Munin::Plugin;
79

    
80
# SQL parameters are read from mysql.txt
81
# There should be no need to change anything after this point
82
my $SQLServer = "";
83
my $SQLUser = "";
84
my $SQLPassword = "";
85
my $SQLDBName = "";
86

    
87
my @result="";
88
my $ScheduleDays=0;
89
my $Recordings=0;
90
my $GraphOption="";
91
my $Recorded=0;
92
my $RecHours=0;
93
my $RecHoursLiveTV=0;
94
my $result="";
95
my $gata="";
96
my $VideoInput=1;
97
 $GraphOption=`basename $0 | sed 's/^mythtv_status_//g' | tr '_' '-'` ;	
98
 chomp $GraphOption;
99

    
100
PrepSQLRead();
101

    
102
#Auto config options
103
 if ($ARGV[0] and $ARGV[0] eq "autoconf" ) {
104
     print "yes\n";
105
     exit 0;
106
 } 
107

    
108
#Config Options
109
##Configuration for encoder, no config data needs to read from anywhere
110
 if ($ARGV[0] and $ARGV[0] eq "config"){
111
   if ($GraphOption eq "encoder") {
112
     print "graph_args --base 1000 --lower-limit 0 --rigid\n";
113
     print "graph_scale off\n";
114
     print "graph_info MythTV encoder information\n";
115
     print "graph_title MythTV Encoders\n";
116
     print "graph_category tv\n";
117
     print "graph_vlabel Encoders\n";
118
     @result=SQLQuery("SELECT `name` FROM `videosource`");
119
     my $First=0;
120
     foreach $gata (@result) {
121
       $gata = clean_fieldname($gata);
122
       print "ActiveEncoders$gata.draw ";
123
       if ( $First == 0 ) {
124
          print "AREA\n";
125
          print "ActiveEncoders$gata.colour FF0000\n";
126
          $First=1;
127
       } else {
128
          print "STACK\n";
129
          print "ActiveEncoders$gata.colour 0000FF\n";
130
       }
131
       print "ActiveEncoders$gata.label Active encoders for videosource '$gata'\n";
132
     }
133
     print "FreeEncoders.draw STACK\n";
134
     print "FreeEncoders.label Inactive encoders\n";
135
     print "FreeEncoders.colour 00FF00\n";
136
     print "HungEncoders.colour 000000\n";
137
     print "HungEncoders.draw LINE1\n";
138
     print "HungEncoders.label Encoders that have hung (no DB update)\n";     
139
     print "HungEncoders.warning 0:0\n";
140
   }
141

    
142
##Configuration for EPG, information read from SQL database
143
   if ($GraphOption eq "epg") {
144
     print "graph_args --base 1000 -l 0\n";
145
     print "graph_info MythTV EPG information\n";
146
     print "graph_scale off\n";
147
     print "graph_title MythTV EPG days/Programs\n";
148
     print "graph_category tv\n";
149
     print "graph_vlabel Days\/Programs\n";
150
     
151
     @result=SQLQuery("SELECT DISTINCT `sourceid` FROM `cardinput`");
152
     $VideoInput = 1;
153
     foreach $gata (@result) {
154
        print "EPGDays$VideoInput.label EPG Data (days) for input $VideoInput\n";
155
        print "EPGDays$VideoInput.info Electronic Program Guide number of days stored\n";
156
        print "EPGPrograms$VideoInput.label Programs in EPG (1000's)  for input $VideoInput\n";
157
        print "EPGPrograms$VideoInput.info Number of programs stored in the Electronic Program Guide (in 1000's)\n";
158
        print "EPGDays$VideoInput.min 0\n";
159
        print "EPGPrograms$VideoInput.min 0\n";
160
        $VideoInput++;
161
     }
162
   }
163

    
164
##Configuration for jobs, no config data needs to read from anywhere
165
   if ($GraphOption eq "job") {
166
     print "graph_args --base 1000 -l 0\n";
167
     print "graph_scale off\n";
168
     print "graph_info MythTV job information\n";
169
     print "graph_title MythTV Jobs\n";
170
     print "graph_category tv\n";
171
     print "graph_vlabel Jobs\n";
172
     print "CommJobs.label Active commflag jobs\n";
173
     print "TransJobs.label Active transcode jobs\n";
174
     print "QueueJobs.label Queued Jobs\n";
175
   }
176

    
177
##Configuration for schedule, no config data needs to read from anywhere
178
   if ($GraphOption eq "schedule") {
179
     print "graph_args --base 1000 -l 0\n";
180
     print "graph_scale off\n";
181
     print "graph_info MythTV schedule information\n";
182
     print "graph_title MythTV Schedule\n";
183
     print "graph_category tv\n";
184
     print "graph_vlabel Programs\n";
185
     print "RecordingRecordings.label Programs that will be recorded\n";
186
     print "RecordingRecordings.info Upcoming programs that will be recorded\n";
187
     print "RecordingRecordings.draw AREA\n";
188
     print "RecordingConflict.label Recording Conflicts\n";
189
     print "RecordingConflict.info Upcoming programs that won't be recorded due to tuner conflicts\n";
190
     print "RecordingConflict.draw STACK\n";
191
     print "RecordingConflict.colour FF0000\n";
192
     print "RecordingConflict.warning 0:0\n";
193
     print "RecordingRepeats.label Recording repeats (Already recorded)\n";
194
     print "RecordingRepeats.info Upcoming programs that are already recorded (Repeats)\n";
195
     print "RecordingRepeats.draw  STACK\n";
196
     print "RecordingRepeats.colour 0000FF\n";
197
     print "RecordingDisabled.label Disabled recordings\n";
198
     print "RecordingDisabled.info Recordings will not be recorded (Inactive/Canceled/Aborted/Manual/Free Diskspace etc)\n";
199
     print "RecordingDisabled.draw STACK\n";
200
     print "RecordingSchedules.label Scheduled recordings\n";
201
     print "RecordingSchedules.info Number of schedules defined (Series only counts as one item)\n";
202
     print "RecordingSchedules.draw LINE2\n";
203
     print "RecordingSchedules.colour 000000\n";
204
   }
205

    
206
##Configuration for recorded
207
   if ($GraphOption eq "recorded") {
208
     print "graph_args --base 1000 -l 0\n";
209
     print "graph_scale off\n";
210
     print "graph_info MythTV recorded information\n";
211
     print "graph_title MythTV Recorded\n";
212
     print "graph_category tv\n";
213
     print "graph_vlabel Programs or Hours\n";
214
     print "graph_order RecLiveTV RecHoursDelete RecHoursExpire RecHours Recorded Watched \n";
215

    
216
     print "RecLiveTV.min 0\n";
217
     print "RecLiveTV.label Hours recorded (Live TV)\n";
218
     print "RecLiveTV.colour 0000FF\n";
219
     print "RecLiveTV.info Hours recorded - Live TV\n";
220
     print "RecLiveTV.draw AREA\n";
221

    
222
     print "RecHours.min 0\n";
223
     print "RecHours.label Hours recorded (Not marked as auto expire)\n";
224
     print "RecHours.colour 00FF00\n";
225
     print "RecHours.info Hours recorded - using schedule (Not marked as auto expire)\n";
226
     print "RecHours.draw STACK\n";
227

    
228
     print "RecHoursExpire.label Hours recorded (marked as auto expire)\n";
229
     print "RecHoursExpire.info Hours recorded - using schedule (marked as auto expire)\n";
230
     print "RecHoursExpire.draw STACK\n";
231
     print "RecHoursExpire.colour 00C000\n";
232

    
233
     print "RecHoursDelete.label Hours recorded (delete pending)\n";
234
     print "RecHoursDelete.info Hours recorded - using schedule (delete pending)\n";
235
     print "RecHoursDelete.draw STACK\n";
236
     print "RecHoursDelete.colour 008000\n";
237

    
238
     print "Recorded.label Programs recorded\n";
239
     print "Recorded.colour FF0000\n";
240
     print "Recorded.info Number of programs recorded (Scheduled)\n";
241
     print "Recorded.draw LINE1\n";
242

    
243
     print "Watched.label Programs already watched\n";
244
     print "Watched.colour 000000\n";
245
     print "Watched.info Programes that have been watched at least once\n";
246
     print "Watched.draw LINE1\n";
247
   }
248
   exit 0;
249
 }
250

    
251
#Actually dump data to Munin
252
 if ($GraphOption eq "encoder") {
253
   @result=SQLQuery("SELECT videosource.name FROM `videosource` ");
254
   my %Names;
255
   my $Name="";
256
   foreach $Name (@result) {
257
     $Names{$Name}=0;
258
   }
259
   @result=SQLQuery("SELECT count(*) FROM `capturecard` ");
260
   my $FreeRecorders=$result[0];
261
   my $ActiveTuners=0;
262
   @result=SQLQuery("SELECT videosource.name, count( inuseprograms.recusage ) 
263
                     FROM   inuseprograms, channel, videosource
264
                     WHERE  inuseprograms.recusage = 'recorder'
265
                     AND    inuseprograms.chanid   = channel.chanid
266
                     AND    channel.sourceid       = videosource.sourceid
267
                     AND    (UNIX_TIMESTAMP( NOW( )) - UNIX_TIMESTAMP(inuseprograms.lastupdatetime)) / 60 < 20
268
                     GROUP BY videosource.sourceid
269
                    ");
270
   foreach $gata (@result) {
271
     if ( $Name eq "" ) {
272
       $Name=$gata;
273
     } else {
274
         $Names{$Name} = $gata;
275
         $Name="";
276
         $FreeRecorders=$FreeRecorders-$gata;
277
     }
278
   }
279
   foreach $Name (keys %Names) {
280
     if ( $Name ne "" ) {
281
       print "ActiveEncoders" . clean_fieldname($Name) . ".value  $Names{$Name}\n";
282
     }
283
   }
284
   print "FreeEncoders.value $FreeRecorders\n";
285
   @result=SQLQuery("SELECT count(inuseprograms.recusage)
286
                     from inuseprograms  
287
                     where inuseprograms.recusage = 'recorder'   
288
                     and (UNIX_TIMESTAMP( NOW( )) - UNIX_TIMESTAMP(inuseprograms.lastupdatetime)) / 60 > 20");
289
   print "HungEncoders.value $result[0]\n";
290
 }
291

    
292
#Get number of days of EPG per video source
293
 if ($GraphOption eq "epg") {
294
   @result=SQLQuery("SELECT (UNIX_TIMESTAMP( MAX( starttime ) ) - UNIX_TIMESTAMP( NOW( ) ) ) /86400 FROM program GROUP BY `listingsource` ");
295
   $VideoInput = 1;
296
   foreach $gata (@result) {
297
      print "EPGDays$VideoInput.value $gata\n";
298
      $VideoInput++;
299
   }  
300

    
301
#Get number of programs in EPG per video source
302
   $VideoInput = 1;
303
   @result=SQLQuery("SELECT count(*)/1000 FROM `program` GROUP BY `listingsource` ");
304
   foreach $gata (@result) {
305
      print "EPGPrograms$VideoInput.value $gata\n";
306
      $VideoInput++;
307
   }
308
 }
309

    
310
#Get active job queue
311
 if ($GraphOption eq "job") {
312
   @result=SQLQuery("SELECT count(*) FROM `inuseprograms` WHERE `recusage` = 'flagger' ");
313
   print "CommJobs.value $result[0]\n";
314

    
315
   @result=SQLQuery("SELECT count(*) FROM `inuseprograms` WHERE `recusage` = 'transcoder' ");
316
   print "TransJobs.value $result[0]\n";
317

    
318
   @result=SQLQuery("SELECT count(*) FROM `jobqueue` WHERE `status` = '1' ");
319
   print "QueueJobs.value $result[0]\n";
320
 }
321

    
322
#Get schedule
323
 if ($GraphOption eq "schedule") {
324
   @result=SQLQuery("SELECT COUNT(*) FROM `record`");
325
   print "RecordingSchedules.value $result[0]\n";
326

    
327
#Connect to mythtv using the MythTV object 
328
   my $Repeats=0;
329
   my $Recordings=0;
330
   my $Conflicts=0;
331
   my $Disabled=0;
332
   our $show;
333
   my $Myth = new MythTV();
334
#Grab the schedule list from the backend
335
   my %rows = $Myth->backend_rows('QUERY_GETALLPENDING', 2);
336
   foreach my $row (@{$rows{'rows'}}) {
337
     $show = new MythTV::Program(@$row);
338
     $Recordings++ if (is_scheduled($show->{'recstatus'}));
339
     $Repeats++ if (is_duplicate($show->{'recstatus'}));
340
     $Disabled++ if (is_deactivated($show->{'recstatus'}));
341
     $Conflicts++ if(is_conflict($show->{'recstatus'}));
342
   }
343
   print "RecordingRepeats.value $Repeats\n";
344
   print "RecordingRecordings.value $Recordings\n";
345
   print "RecordingConflict.value $Conflicts\n";
346
   print "RecordingDisabled.value $Disabled\n";
347
 }
348

    
349
#Get recorded
350
 if ($GraphOption eq "recorded") {
351
   @result=SQLQuery("select sum(UNIX_TIMESTAMP(recorded.endtime) - UNIX_TIMESTAMP(recorded.starttime))/3600 from recorded where recorded.recgroup = 'LiveTV' ");
352
   print "RecLiveTV.value $result[0]\n";
353

    
354
   @result=SQLQuery("select sum(UNIX_TIMESTAMP(recorded.endtime) - UNIX_TIMESTAMP(recorded.starttime))/3600 from recorded where recorded.recgroup != 'LiveTV' and autoexpire != 1 and deletepending  != 1");
355
   print "RecHours.value $result[0]\n";
356

    
357
   @result=SQLQuery("select sum(UNIX_TIMESTAMP(recorded.endtime) - UNIX_TIMESTAMP(recorded.starttime))/3600 from recorded where recorded.recgroup != 'LiveTV' and autoexpire = 1");
358
   print "RecHoursExpire.value $result[0]\n";
359

    
360
   @result=SQLQuery("select sum(UNIX_TIMESTAMP(recorded.endtime) - UNIX_TIMESTAMP(recorded.starttime))/3600 from recorded where deletepending  = 1");
361
   print "RecHoursDelete.value $result[0]\n";
362

    
363
   @result=SQLQuery("SELECT count( recorded.chanid ) FROM recorded");
364
   print "Recorded.value $result[0]\n";
365

    
366
   @result=SQLQuery("SELECT count(*) FROM `recorded` WHERE recorded.watched != 0");
367
   print "Watched.value $result[0]\n";
368

    
369
 }
370
exit 0;
371

    
372

    
373
#Try and read MythTV configuration parameters from mysql.txt (This could be in several places)
374
sub PrepSQLRead {
375
    my $hostname = `hostname`;
376
    chomp($hostname);
377
    
378
# Read the mysql.txt file in use by MythTV. Could be in a couple places, so try the usual suspects
379
    my $found = 0;
380
    my @mysql = ('/usr/local/share/mythtv/mysql.txt',
381
                 '/usr/share/mythtv/mysql.txt',
382
                 '/etc/mythtv/mysql.txt',
383
                 '/usr/local/etc/mythtv/mysql.txt',
384
                 'mysql.txt'
385
                );
386
    foreach my $file (@mysql) {
387
        next unless (-e $file);
388
        $found = 1;
389
        open(CONF, $file) or die "Unable to open $file:  $!\n\n";
390
        while (my $line = <CONF>) {
391
        # Cleanup
392
            next if ($line =~ /^\s*#/);
393
            $line =~ s/^str //;
394
            chomp($line);
395
        # Split off the var=val pairs
396
            my ($var, $val) = split(/\=/, $line, 2);
397
            next unless ($var && $var =~ /\w/);
398
            if ($var eq 'DBHostName') {
399
                $SQLServer = $val;
400
            }
401
            elsif ($var eq 'DBUserName') {
402
                $SQLUser = $val;
403
            }
404
            elsif ($var eq 'DBName') {
405
                $SQLDBName = $val;
406
            }
407
            elsif ($var eq 'DBPassword') {
408
                $SQLPassword = $val;
409
            }
410
        # Hostname override
411
            elsif ($var eq 'LocalHostName') {
412
                $hostname = $val;
413
            }
414
        }
415
        close CONF;
416
    }
417
    die "Unable to locate mysql.txt:  $!\n\n" unless ($found && $SQLServer);
418
    return 0;
419
}
420

    
421
#Perform  SQL query
422
sub SQLQuery {
423
   my  ($QUERY) = @_;
424
   my @data;
425
   my $ref;
426
   my $dbh = DBI->connect_cached("DBI:mysql:$SQLDBName:$SQLServer", $SQLUser, $SQLPassword) 
427
         or die "Couldn't connect to database: " . DBI->errstr;
428
   my $table_data = $dbh->prepare($QUERY) or die "Couldn't prepare statement: " . $dbh->errstr;
429
   $table_data->execute or die "Couldn't execute statement: " . $table_data->errstr;
430

    
431
   while ( $ref = $table_data->fetchrow_arrayref() )  {
432
      push (@data,@{$ref})
433
   }
434
   if ($data[0]) {
435
     return @data;
436
   } else {
437
     return 0;
438
   }   
439
}
440

    
441
# Returns true if the show is scheduled to record
442
    sub is_scheduled {
443
        my $recstatus = (shift() or 0);
444
        return (($MythTV::recstatus_willrecord == $recstatus) ||
445
                ($MythTV::recstatus_recorded == $recstatus) ||
446
                ($MythTV::recstatus_recording == $recstatus));
447
    }
448

    
449
# Returns true if the show is a duplicate
450
    sub is_duplicate {
451
        my $recstatus = (shift() or 0);
452
        return (($MythTV::recstatus_repeat == $recstatus) ||
453
                ($MythTV::recstatus_previousrecording == $recstatus) ||
454
                ($MythTV::recstatus_currentrecording == $recstatus));
455
    }
456

    
457
# Returns true if the show cannot be recorded due to a conflict
458
    sub is_conflict {
459
        my $recstatus = (shift() or 0);
460
        return ($MythTV::recstatus_conflict == $recstatus);
461
    }
462

    
463
# Returns true if the recording is deactivated
464
    sub is_deactivated {
465
        my $recstatus = (shift() or 0);
466
        return (($MythTV::recstatus_inactive == $recstatus) ||
467
                ($MythTV::recstatus_toomanyrecordings == $recstatus) ||
468
                ($MythTV::recstatus_cancelled == $recstatus) ||
469
                ($MythTV::recstatus_deleted == $recstatus) ||
470
                ($MythTV::recstatus_aborted == $recstatus) ||
471
                ($MythTV::recstatus_notlisted == $recstatus) ||
472
                ($MythTV::recstatus_dontrecord == $recstatus) ||
473
                ($MythTV::recstatus_lowdiskspace == $recstatus) ||
474
                ($MythTV::recstatus_tunerbusy == $recstatus) ||
475
                ($MythTV::recstatus_neverrecord == $recstatus) ||
476
                ($MythTV::recstatus_earliershowing == $recstatus) ||
477
                ($MythTV::recstatus_latershowing == $recstatus));
478
    }