#!/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 < 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 ( ) { 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 = ) ) { chomp $line; if ($line =~ s/\\$//) { $line .= ; 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 ); }