234 lines
4.0 KiB
Perl
Executable File
234 lines
4.0 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
#
|
|
# This code is intended to update the modules installed within each
|
|
# Xen guest domain to the named version.
|
|
#
|
|
# It should be fairly safe, but I make no promises - hence why this
|
|
# is an example.
|
|
#
|
|
# Steve
|
|
# --
|
|
#
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use File::Path qw/ rmtree /;
|
|
use File::Temp qw/ tempdir /;
|
|
|
|
|
|
my $modules = shift;
|
|
if ( ! defined( $modules ) )
|
|
{
|
|
print <<EOF;
|
|
|
|
Usage: $0 <modules>
|
|
|
|
eg: $0 2.6.18.xx|/usr/lib/modules/nn.nn.nn-xen
|
|
|
|
EOF
|
|
exit;
|
|
}
|
|
|
|
|
|
#
|
|
# Make sure the path is fully qualified.
|
|
#
|
|
if ( $modules !~ /^[\/\\]/ )
|
|
{
|
|
$modules = "/lib/modules/" . $modules;
|
|
}
|
|
|
|
|
|
#
|
|
# Make sure the module directory exists.
|
|
#
|
|
if ( ! -d $modules )
|
|
{
|
|
print "The modules directory $modules doesn't exist.\n";
|
|
exit;
|
|
}
|
|
|
|
|
|
#
|
|
# OK now we have the modules so we need to:
|
|
#
|
|
# 0. Read our configuration file.
|
|
# 1. Find each xen guest.
|
|
# 2. Ensure it isn't running (TODO)
|
|
# 3. Mount the disk image.
|
|
# 4. Remove existing modules, and copy in the specified ones.
|
|
#
|
|
#
|
|
|
|
|
|
my %CONFIG;
|
|
readConfigurationFile( "/etc/xen-tools/xen-tools.conf" );
|
|
|
|
|
|
foreach my $guest ( findGuests() )
|
|
{
|
|
print "Attempting to update guest: $guest\n";
|
|
|
|
#
|
|
# Create a temporary directory to mount the disk upon.
|
|
#
|
|
my $tmp = tempdir( CLEANUP => 1 );
|
|
|
|
#
|
|
# Mount the disk.
|
|
#
|
|
if ( $CONFIG{'dir'} )
|
|
{
|
|
# The loopback image.
|
|
my $img = $CONFIG{'dir'} . "/domains/" . $guest . "/disk.img";
|
|
system( "mount -o loop $img $tmp" );
|
|
}
|
|
elsif ( $CONFIG{'lvm'} )
|
|
{
|
|
# The LVM volume
|
|
my $img = "/dev/" . $CONFIG{'lvm'} . "/$guest-disk";
|
|
system( "mount $img $tmp" );
|
|
}
|
|
else
|
|
{
|
|
print "Unhandled disk format - can't mount\n";
|
|
next;
|
|
}
|
|
|
|
|
|
#
|
|
# We've got it mounted.
|
|
#
|
|
print "\tMounted disk image.\n";
|
|
|
|
# make sure we have a directory
|
|
if ( ! -d $tmp . "/lib/modules" )
|
|
{
|
|
print "\tMissing modules. Skipping\n";
|
|
next;
|
|
}
|
|
#
|
|
# Remove the existing module directories.
|
|
#
|
|
`rm -rf $tmp/lib/modules`;
|
|
mkdir $tmp . "/lib/modules";
|
|
print "\tRemoved existing modules\n";
|
|
|
|
#
|
|
# Copy existing directory.
|
|
#
|
|
if ( -d $tmp . "/lib/modules" )
|
|
{
|
|
`cp -R $modules $tmp/lib/modules/`;
|
|
print "\tCopied over $modules\n";
|
|
}
|
|
else
|
|
{
|
|
print "No module directory .. weirdness\n";
|
|
}
|
|
|
|
#
|
|
# Unmount
|
|
#
|
|
system( "umount $tmp" );
|
|
print "\tUnmounted disk image.\n\n";
|
|
}
|
|
|
|
|
|
|
|
|
|
=begin doc
|
|
|
|
Find each xen guest upon the system.
|
|
|
|
=end doc
|
|
|
|
=cut
|
|
|
|
sub findGuests
|
|
{
|
|
my @results;
|
|
|
|
#
|
|
# Assume xen-tools.
|
|
#
|
|
foreach my $file ( glob( "/etc/xen/*.cfg" ) )
|
|
{
|
|
#
|
|
# Find the name.
|
|
#
|
|
open( INPUT, "<" , $file );
|
|
foreach my $line ( <INPUT> )
|
|
{
|
|
chomp( $line );
|
|
if ( $line =~ /name\s*=\s*['"]([^'"]+)["']/ )
|
|
{
|
|
push @results, $1;
|
|
}
|
|
}
|
|
close( INPUT );
|
|
}
|
|
return( sort( @results ) );
|
|
}
|
|
|
|
|
|
|
|
|
|
=begin doc
|
|
|
|
Read the configuration file specified.
|
|
|
|
=end doc
|
|
|
|
=cut
|
|
|
|
sub readConfigurationFile
|
|
{
|
|
my ($file) = ( @_ );
|
|
|
|
open( FILE, "<", $file ) or die "Cannot read file '$file' - $!";
|
|
|
|
my $line = "";
|
|
|
|
while (defined($line = <FILE>) )
|
|
{
|
|
chomp $line;
|
|
if ($line =~ s/\\$//)
|
|
{
|
|
$line .= <FILE>;
|
|
redo unless eof(FILE);
|
|
}
|
|
|
|
# Skip lines beginning with comments
|
|
next if ( $line =~ /^([ \t]*)\#/ );
|
|
|
|
# Skip blank lines
|
|
next if ( length( $line ) < 1 );
|
|
|
|
# Strip trailing comments.
|
|
if ( $line =~ /(.*)\#(.*)/ )
|
|
{
|
|
$line = $1;
|
|
}
|
|
|
|
# Find variable settings
|
|
if ( $line =~ /([^=]+)=([^\n]+)/ )
|
|
{
|
|
my $key = $1;
|
|
my $val = $2;
|
|
|
|
# Strip leading and trailing whitespace.
|
|
$key =~ s/^\s+//;
|
|
$key =~ s/\s+$//;
|
|
$val =~ s/^\s+//;
|
|
$val =~ s/\s+$//;
|
|
|
|
# Store value.
|
|
$CONFIG{ $key } = $val;
|
|
}
|
|
}
|
|
|
|
close( FILE );
|
|
}
|