Subversion Repositories sysadmin_scripts

Rev

Rev 143 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
140 rodolico 1
#! /usr/bin/env perl
2
 
3
use strict;
4
use warnings;
5
use YAML::XS qw(DumpFile LoadFile); # libyaml-libyaml-perl
6
use Getopt::Std;
7
 
8
$main::VERSION = '0.1';
9
 
10
my $dbFile = 'virtinfo_db.yaml';
11
my $lockFile = 'virtinfo.lock';
12
 
13
 
14
use Data::Dumper;
15
 
16
 
17
#
18
# find where the script is actually located as cfg should be there
19
#
20
sub getScriptLocation {
21
   use strict;
22
   use File::Spec::Functions qw(rel2abs);
23
   use File::Basename;
24
   return dirname(rel2abs($0));
25
}
26
 
27
sub main::HELP_MESSAGE {
28
   print "\nScript reads running virtuals and store results in database\n\n";
29
   print "-s          Show database and exit\n";
30
   print "-c filename Use alternative database\n";
31
   print "-n          Don't update the database\n";
32
   print "-v          Be Verbose (show some stats)\n";
33
   print "-r          Report - only display if something changed\n";
34
}
35
 
36
sub main::VERSION {
37
   &HELP_MESSAGE();
38
}
39
 
40
sub readDB {
41
   my $lock = shift;
42
   my $db;
43
   sleep(5) if -e $lockFile;
44
   die "Could not get lock on $dbFile: Aborting\n" if -e $lockFile;
45
   `touch $lockFile` unless $lock;
46
   $db = LoadFile( $dbFile ) if ( -e $dbFile );
47
   return $db;
48
}
49
 
50
sub saveDB {
51
   my ($db, $verbose)  = @_;
52
   print "Updating database\n" if $verbose;
53
   DumpFile( $dbFile, $db );
54
}
55
 
56
# many of the outputs produce key:value pairs
57
# we will parse this into a hash
58
sub parseDelimited {
59
   my $delimiter = shift;
60
   my %return;
61
   while ( my $line = shift ) {
62
      chomp $line;
63
      next unless $line;
64
      my ( $key, $value ) = split( /$delimiter/, $line );
65
      $return{lc &trim($key) } = &trim($value);
66
   }
67
   return \%return;
68
}
69
 
70
 
71
sub getNode {
72
   my @info = `virsh nodeinfo`;
73
   my $hypervisor = &parseDelimited( ':', @info );
74
   return $hypervisor;
75
}
76
 
77
 
78
sub getRunningVirtuals {
79
   my @domains = `virsh list`;
80
   chomp @domains;
81
   my %domains;
82
   foreach my $domain ( @domains ) {
83
      # skip the headers
84
      next if $domain =~ m/^(Id)|(--)/;
85
      if ( $domain =~ m/^\s*(\d+)\s+([^\s]+)\s/ ) {
86
         $domains{$2}{'id'} = $1;
87
      }
88
   }
89
   return \%domains;
90
}
91
 
92
sub updateDB {
93
   my ( $node, $self, $verbose ) = @_; 
94
   # get a list of all running virtuals
95
   my $virts = &getRunningVirtuals();
96
   my @a = sort keys %$virts;
97
   my @b = sort keys  %{ $node->{$self}->{'virtuals'} };
98
   return 0 # return if they are the same, no action needed
99
      if &compareArray( \@a, \@b );
100
   # something has changed, so load all information again
101
   print "Something has changed, so loading everything again\n" if $verbose;
102
   $node->{$self}->{'hypervisor'} = &getNode();
103
   $node->{$self}->{'virtuals'} = $virts;;
104
   foreach my $domain ( keys %{$node->{$self}->{'virtuals'}} ) {
105
      next unless $domain;
106
      my @info = `virsh dominfo $domain`;
107
      my $vnc = `virsh vncdisplay $domain`;
108
      chomp $vnc;
109
      $vnc =~ m/^.*:(\d+)$/;
110
      push @info, "vncport: $1";
111
      $node->{$self}->{'virtuals'}->{$domain} = &parseDelimited( ':', @info );
112
   }
113
   return ( 1, $node );;
114
}
115
 
116
 
117
# remove leading and trailing whitespace from string
118
sub trim {
119
   my $string = shift;
120
   $string =~ s/^\s+|\s+$//;
121
   return $string;
122
}
123
 
143 rodolico 124
sub showReport {
140 rodolico 125
   my $conf = shift;
126
   foreach my $node ( keys %$conf ) {
127
      print "$node\n";
128
      foreach my $virt ( keys %{ $conf->{$node}->{'virtuals'} } ) {
129
         print "\t$virt\n";
130
      }
131
   }
132
}
133
 
134
 
135
sub compareArray {
136
   my ($arr1, $arr2 ) = @_;
137
   # if they don't have the same number of elements, not equal
138
   return 0 if @$arr1 != @$arr2;
139
   for ( my $i = 0; $i < scalar( @$arr1 ); $i++ ) {
140
      return 0 unless $$arr1[$i] eq $$arr2[$i];
141
   }
142
   return 1;
143
}
144
 
145
 
146
my $path = &getScriptLocation() . '/';
147
$dbFile = $path . $dbFile;
148
$lockFile = $path . $lockFile;
149
 
150
 
151
$Getopt::Std::STANDARD_HELP_VERSION = 1;
152
my %options = ();
153
getopts( 'vosrc:n', \%options );
154
 
155
if ( $options{'o'} ) {
156
   print "Dumping cli parameters\n";
157
   foreach my $option ( keys %options ) {
158
      print "$option\t[$options{$option}]\n";
159
   }
160
}
161
 
162
 
163
my $db = &readDB( $options{'n'} );
164
 
165
my $self = `hostname -f`;
166
chomp $self;
167
 
168
if ( $options{'s'} ) {
143 rodolico 169
   &showReport( $db );
140 rodolico 170
} elsif ( ! $options{ 'n' } ) {
171
   print STDERR "Updating the database\n" if $options{'v'};
172
   my $dirty = 0;
173
   ( $dirty, $db ) = &updateDB( $db,$self, $options{'v'} );
174
   if ( $dirty ) {
175
      print "Virtuals changed on $self\n" if ($options{'r'});
176
      &saveDB( $db, $options{'v'} );
177
   }
178
}
179
 
180
`rm $lockFile` if -e $lockFile;
181
 
182
 
183
1;