tuto:virtualisation:virt_scripts

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
Prochaine révision Les deux révisions suivantes
tuto:virtualisation:virt_scripts [03/04/2010 00:25]
dani
tuto:virtualisation:virt_scripts [22/06/2010 20:02]
dani
Ligne 1: Ligne 1:
 +FIXME: cette page est obsolète, et n'a été utilisé que pour la création du paquet virt-stack
 +
 Contenue du paquet: Contenue du paquet:
   * script de sauvegarde virt-backup.pl   * script de sauvegarde virt-backup.pl
Ligne 6: Ligne 8:
  
 ====== Script d'hibernation/réveil des VM lors de l'arrête/démarrage de l'hôte ====== ====== Script d'hibernation/réveil des VM lors de l'arrête/démarrage de l'hôte ======
 +
 +Ce script ne devrait plus être nécessaire à partit de libvirt-0.8.0 (qui intègre de façon native une fonction "managed save" qui permet de réveiller une VM depuis un fichier state, simplement en démarrant le domaine)
  
 <code bash> <code bash>
Ligne 164: Ligne 168:
  
 ===== Script de configuration des permissions qui vont bien ===== ===== Script de configuration des permissions qui vont bien =====
 +Hook script pour qemu (/etc/libvirt/hook/qemu)
 +<code bash>
 +#!/bin/bash
 +
 +VM=shift
 +OP=shift
 +SUBOP=shift
 +
 +VOLS=(cat /dev/stdin | xmlstarlet sel -t -m \
 +    "/domain/devices/disk/source" -v @dev -v @file -n; done | grep '/')
 +
 +if [ $OP == "start" ]; then
 +    for VOL in $VOLS;do 
 +        chcon -t virt_image_t $VOL
 +    done
 +fi
 +
 +exit 0
 +</code>
 +
 +Hook script pour le démon (/etc/libvirt/hook/daemon)
 +
 +<code bash>
 +#!/bin/bash
 +
 +OBJ=shift
 +OP=shift
 +
 +if [ $OP == "start" ]; then
 +    for DIR in /var/lib/libvirt/qemu /var/run/libvirt/qemu /var/cache/libvirt/qemu; do
 +        [ -d $DIR ] || mkdir -p $DIR
 +        chown qemu:qemu $DIR
 +    done
 +fi
 +
 +exit 0
 +</code>
  
 Un chcon tout les supports utilisés par une VM: Un chcon tout les supports utilisés par une VM:
Ligne 201: Ligne 242:
 <code perl> <code perl>
 #!/usr/bin/perl -w #!/usr/bin/perl -w
 + 
 # AUTHOR # AUTHOR
 #   Daniel Berteaud <daniel@firewall-services.com> #   Daniel Berteaud <daniel@firewall-services.com>
Ligne 221: Ligne 262:
 #   along with this program; if not, write to the Free Software #   along with this program; if not, write to the Free Software
 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- +  
- +  
 + 
 # This script allows you to backup Virtual Machines managed by libvirt. # This script allows you to backup Virtual Machines managed by libvirt.
 # It has only be tested with KVM based VM # It has only be tested with KVM based VM
Ligne 230: Ligne 271:
 # * optionnally the memory (if --state flag is given) # * optionnally the memory (if --state flag is given)
 # * the XML description of the VM # * the XML description of the VM
 + 
 # These files are writen in a temporary backup dir. Everything is done # These files are writen in a temporary backup dir. Everything is done
 # in order to minimize donwtime of the guest. For example, it takes # in order to minimize donwtime of the guest. For example, it takes
Ligne 236: Ligne 277:
 # just paused for a couple of seconds. Once this is done, the guest is # just paused for a couple of seconds. Once this is done, the guest is
 # resumed, and the script starts to dump the snapshot. # resumed, and the script starts to dump the snapshot.
 + 
 # Once a backup is finished, you'll have several files in the backup # Once a backup is finished, you'll have several files in the backup
 # directory. Let's take an example with a VM called my_vm which has # directory. Let's take an example with a VM called my_vm which has
Ligne 245: Ligne 286:
 # * my_vm_hdb.img: this file is an image of the hdb drive of the guest # * my_vm_hdb.img: this file is an image of the hdb drive of the guest
 # * my_vm.state: this is a dump of the memory (result of virsh save my_vm my_vm.state) # * my_vm.state: this is a dump of the memory (result of virsh save my_vm my_vm.state)
 + 
 # This script was made to be ran with BackupPC pre/post commands. # This script was made to be ran with BackupPC pre/post commands.
 # In the pre-backup phase, you dump everything then, backuppc backups, # In the pre-backup phase, you dump everything then, backuppc backups,
 # compress, pools etc... the dumped file. Eventually, when the backup is finished # compress, pools etc... the dumped file. Eventually, when the backup is finished
 # The script is called with the --cleanup flag, which cleanups everything. # The script is called with the --cleanup flag, which cleanups everything.
 + 
 # Some examples: # Some examples:
 # #
Ligne 257: Ligne 298:
 # compress the dumped disks (uses gzip by default) # compress the dumped disks (uses gzip by default)
 # virt-backup.pl --dump --vm=mail01,devsrv --state --exclude=vdb,hdb --compress # virt-backup.pl --dump --vm=mail01,devsrv --state --exclude=vdb,hdb --compress
 + 
 # Remove all the files related to mail01 VM in the backup directory # Remove all the files related to mail01 VM in the backup directory
 # virt-backup.pl --cleanup --vm=mail01 # virt-backup.pl --cleanup --vm=mail01
 + 
 # Backup devsrv, use 10G for LVM snapshots (if available), do not dump the memory # Backup devsrv, use 10G for LVM snapshots (if available), do not dump the memory
 # (the guest will just be paused while we take a snapshot) # (the guest will just be paused while we take a snapshot)
 # Keep the lock file present after the dump # Keep the lock file present after the dump
 # virt-backup.pl --dump --vm=devsrv --snapsize=10G --keep-lock # virt-backup.pl --dump --vm=devsrv --snapsize=10G --keep-lock
 + 
 # Backup devsrv, and disable LVM snapshots # Backup devsrv, and disable LVM snapshots
 # virt-backup.pl --dump --vm=devsrv --no-snapshot # virt-backup.pl --dump --vm=devsrv --no-snapshot
 + 
 # Backup mail01, and enable debug (verbose output) # Backup mail01, and enable debug (verbose output)
 # virt-backup.pl --dump --vm=mail01 --debug # virt-backup.pl --dump --vm=mail01 --debug
- +  
- +  
- +  
- +  
 + 
 ### TODO: ### TODO:
-# - Make it more robust (script crash sometime while trying to restore 
-#        Probably a bug somewhere between libvirt and Sys::Virt) 
-# - Test with images as backend. Should just work, but without the snapshot function 
 # - Add snapshot (LVM) support for image based disk ? (should we detect the mount moint, and block device # - Add snapshot (LVM) support for image based disk ? (should we detect the mount moint, and block device
 #    of the storage or let the user specify it with a --logical ?) #    of the storage or let the user specify it with a --logical ?)
Ligne 285: Ligne 323:
 # - Check if compression utilies are available # - Check if compression utilies are available
 # - Support per vm excludes in one run # - Support per vm excludes in one run
- +  
- +  
 + 
 ### CHANGES ### CHANGES
 # * 26/03/2010 # * 26/03/2010
 # - Initial packaged version # - Initial packaged version
 + 
 use XML::Simple; use XML::Simple;
 use Sys::Virt; use Sys::Virt;
 use Getopt::Long; use Getopt::Long;
 + 
 # Some constant # Some constant
 + 
 our %opts = (); our %opts = ();
 our @vms = (); our @vms = ();
 our @excludes = (); our @excludes = ();
 + 
 # Sets some defaults values # Sets some defaults values
 $opts{backupdir} = '/var/lib/libvirt/backup'; $opts{backupdir} = '/var/lib/libvirt/backup';
Ligne 318: Ligne 356:
 $opts{wasrunning} = 1; $opts{wasrunning} = 1;
 $opts{bs} = "1M"; $opts{bs} = "1M";
 + 
 # get command line arguments # get command line arguments
 GetOptions( GetOptions(
Ligne 327: Ligne 365:
     "backupdir=s"  => \$opts{backupdir},     "backupdir=s"  => \$opts{backupdir},
     "vm=s"         => \@vms,     "vm=s"         => \@vms,
-    "cleanup"      => \$opts{post}, +    "cleanup"      => \$opts{cleanup}, 
-    "dump"         => \$opts{pre},+    "dump"         => \$opts{dump},
     "connect=s"    => \$opts{connect},     "connect=s"    => \$opts{connect},
     "snapshot!"    => \$opts{snapshot},     "snapshot!"    => \$opts{snapshot},
Ligne 336: Ligne 374:
     "help"         => \$opts{help}     "help"         => \$opts{help}
 ); );
- +  
 + 
 # Set compression settings # Set compression settings
 if ($opts{compress} eq 'lzop'){ if ($opts{compress} eq 'lzop'){
Ligne 354: Ligne 392:
     $opts{compext} = ".xz";     $opts{compext} = ".xz";
     $opts{compcmd} = "xz -c";     $opts{compcmd} = "xz -c";
 +}
 +elsif ($opts{compress} eq 'lzip'){
 +    $opts{compext} = ".lz";
 +    $opts{compcmd} = "lzip -c";
 +}
 +elsif ($opts{compress} eq 'plzip'){
 +    $opts{compext} = ".lz";
 +    $opts{compcmd} = "plzip -c";
 } }
 # Default is gzip # Default is gzip
Ligne 364: Ligne 410:
     $opts{compcmd} = "cat";     $opts{compcmd} = "cat";
 } }
 + 
 # Allow comma separated multi-argument # Allow comma separated multi-argument
 @vms = split(/,/,join(',',@vms)); @vms = split(/,/,join(',',@vms));
 @excludes = split(/,/,join(',',@excludes)); @excludes = split(/,/,join(',',@excludes));
- +  
- +  
 + 
 # Stop here if we either have dump and cleanup, no dump and no cleanup, no vm # Stop here if we either have dump and cleanup, no dump and no cleanup, no vm
 # Or the help flag is present # Or the help flag is present
Ligne 382: Ligne 428:
     exit 1;     exit 1;
 } }
 + 
 if (! -d $opts{backupdir} ){ if (! -d $opts{backupdir} ){
     print "$opts{backupdir} is not a valid directory\n";     print "$opts{backupdir} is not a valid directory\n";
     exit 1;     exit 1;
 } }
 + 
 # Connect to libvirt # Connect to libvirt
 print "\n\nConnecting to libvirt daemon using $opts{connect} as URI\n" if ($opts{debug}); print "\n\nConnecting to libvirt daemon using $opts{connect} as URI\n" if ($opts{debug});
 our $libvirt = Sys::Virt->new( uri => $opts{connect} ) ||  our $libvirt = Sys::Virt->new( uri => $opts{connect} ) || 
     die "Error connecting to libvirt on URI: $opts{connect}";     die "Error connecting to libvirt on URI: $opts{connect}";
- +  
- +  
 + 
 print "\n" if ($opts{debug}); print "\n" if ($opts{debug});
- +  
 + 
 foreach our $vm (@vms){ foreach our $vm (@vms){
     # Create a new object representing the VM     # Create a new object representing the VM
-    print "Retrieving $vm status from libvirt\n" if ($opts{debug});+    print "Checking $vm status\n\n" if ($opts{debug});
     our $dom = $libvirt->get_domain_by_name($vm) ||     our $dom = $libvirt->get_domain_by_name($vm) ||
         die "Error opening $vm object";         die "Error opening $vm object";
     if ($opts{dump}){     if ($opts{dump}){
-        print "Running dump routine for $vm, as requested by the --dump flag\n" if ($opts{debug});+        print "Running dump routine for $vm, as requested by the --dump flag\n\n" if ($opts{debug});
         $opts{backupdir} .= '/'.$vm;         $opts{backupdir} .= '/'.$vm;
         mkdir $opts{backupdir} || die $!;         mkdir $opts{backupdir} || die $!;
Ligne 410: Ligne 456:
     }     }
     elsif ($opts{cleanup}){     elsif ($opts{cleanup}){
-        print "Running cleanup routine for $vm, as requested by the --cleanup flag\n" if ($opts{debug});+        print "Running cleanup routine for $vm, as requested by the --cleanup flag\n\n" if ($opts{debug});
         run_cleanup();         run_cleanup();
     }     }
Ligne 418: Ligne 464:
     }     }
 } }
- +  
- +  
- +  
 + 
 ############################################################################ ############################################################################
 ##############                FUNCTIONS                 #################### ##############                FUNCTIONS                 ####################
 ############################################################################ ############################################################################
- +  
 + 
 sub run_dump{ sub run_dump{
     # Create a new XML object     # Create a new XML object
     my $xml = new XML::Simple ();     my $xml = new XML::Simple ();
-    my $data = $xml->XMLin( $dom->get_xml_description() ); +    my $data = $xml->XMLin( $dom->get_xml_description(), forcearray => ['disk'); 
 + 
     # STop here if the lock file is present, another dump might be running     # STop here if the lock file is present, another dump might be running
     die "Another backup is running\n" if ( -e "$opts{backupdir}/$vm.lock" );     die "Another backup is running\n" if ( -e "$opts{backupdir}/$vm.lock" );
 + 
     # Lock VM: Create a lock file so only one dump process can run     # Lock VM: Create a lock file so only one dump process can run
     lock_vm();     lock_vm();
 + 
     # Save the XML description     # Save the XML description
     save_xml();     save_xml();
 + 
     # Save the VM state if it's running and --state is present     # Save the VM state if it's running and --state is present
     # (else, just suspend the VM)     # (else, just suspend the VM)
-    $opts{wasrunning} = 0 unless (is_active()); +    $opts{wasrunning} = 0 unless ($dom->is_active()); 
 + 
     if ($opts{wasrunning}){     if ($opts{wasrunning}){
         if ($opts{state}){         if ($opts{state}){
Ligne 453: Ligne 499:
         }         }
     }     }
 + 
     my @disks;     my @disks;
 + 
     # Create a list of disks used by the VM     # Create a list of disks used by the VM
     foreach $disk (@{$data->{devices}->{disk}}){     foreach $disk (@{$data->{devices}->{disk}}){
 + 
         my $source;         my $source;
         if ($disk->{type} eq 'block'){         if ($disk->{type} eq 'block'){
             $source = $disk->{source}->{dev};             $source = $disk->{source}->{dev};
-            +        }
         elsif ($disk->{type} eq 'file'){         elsif ($disk->{type} eq 'file'){
             $source = $disk->{source}->{file};             $source = $disk->{source}->{file};
         }         }
         else{         else{
-          print "\n\nSkiping $source for vm $vm as it's type is $disk->{type}: " . +            print "\nSkiping $source for vm $vm as it's type is $disk->{type}: " . 
-                " and only block and file are supported" if ($opts{debug});+                " and only block and file are supported\n" if ($opts{debug});
             next;               next;  
         }         }
         my $target = $disk->{target}->{dev};         my $target = $disk->{target}->{dev};
 + 
         # Check if the current disk is not excluded         # Check if the current disk is not excluded
         if (!!grep { $_ eq "$target" } @excludes){         if (!!grep { $_ eq "$target" } @excludes){
-            print "\n\nSkiping $source for vm $vm as it's matching one of the excludes: " . +            print "\nSkiping $source for vm $vm as it's matching one of the excludes: " . 
-                join(",",@excludes)."\n" if ($opts{debug});+                join(",",@excludes)."\n\n" if ($opts{debug});
             next;             next;
         }         }
 + 
         # If the device is a disk (and not a cdrom) and the source dev exists         # If the device is a disk (and not a cdrom) and the source dev exists
-        if (($disk->{device} eq 'disk') && (-e $source) && (!$disk->{readonly})){ +        if (($disk->{device} eq 'disk') && (-e $source)){ 
- +  
-            print "\n\nAnalysing disk $source connected on $vm as $target\n" if ($opts{debug}); +            print "\nAnalysing disk $source connected on $vm as $target\n\n" if ($opts{debug}); 
 + 
             # If it's a block device             # If it's a block device
             if ($disk->{type} eq 'block'){             if ($disk->{type} eq 'block'){
-                + 
                 my $time = "_".time();                 my $time = "_".time();
                 # Try to snapshot the source if snapshot is enabled                 # Try to snapshot the source if snapshot is enabled
Ligne 516: Ligne 562:
         }         }
     }     }
 + 
     # Summarize the list of disk to be dumped     # Summarize the list of disk to be dumped
     if ($opts{debug}){     if ($opts{debug}){
-        print "\n\nThe following disks will be dumped:\n";+        print "\n\nThe following disks will be dumped:\n\n";
         foreach $disk (@disks){         foreach $disk (@disks){
             print "Source: $disk->{source}\tDest: $opts{backupdir}/$vm" . '_' . $disk->{target} .             print "Source: $disk->{source}\tDest: $opts{backupdir}/$vm" . '_' . $disk->{target} .
                 ".img$opts{compext}\n";                         ".img$opts{compext}\n";        
         }         }
-        print "\n"; 
     }     }
 + 
     # If livebackup is possible (every block devices can be snapshoted)     # If livebackup is possible (every block devices can be snapshoted)
     # We can restore the VM now, in order to minimize the downtime     # We can restore the VM now, in order to minimize the downtime
Ligne 540: Ligne 585:
         }         }
     }     }
 + 
     # Now, it's time to actually dump the disks     # Now, it's time to actually dump the disks
     foreach $disk (@disks){     foreach $disk (@disks){
 + 
         my $source = $disk->{source};         my $source = $disk->{source};
         my $dest = "$opts{backupdir}/$vm" . '_' . $disk->{target} . ".img$opts{compext}";         my $dest = "$opts{backupdir}/$vm" . '_' . $disk->{target} . ".img$opts{compext}";
- +  
-        print "\nStarting dump of $source to $dest\n" if ($opts{debug});+        print "\nStarting dump of $source to $dest\n\n" if ($opts{debug});
         my $ddcmd = "$opts{ionice} dd bs=$opts{bs} if=$source 2>/dev/null | $opts{nice} $opts{compcmd} > $dest 2>/dev/null";         my $ddcmd = "$opts{ionice} dd bs=$opts{bs} if=$source 2>/dev/null | $opts{nice} $opts{compcmd} > $dest 2>/dev/null";
         unless( system("$ddcmd") == 0 ){         unless( system("$ddcmd") == 0 ){
Ligne 555: Ligne 600:
         destroy_snapshot($source) if ($disk->{type} eq 'snapshot');         destroy_snapshot($source) if ($disk->{type} eq 'snapshot');
     }     }
 + 
     # If the VM was running before the dump, restore (or resume) it     # If the VM was running before the dump, restore (or resume) it
     if ($opts{wasrunning}){     if ($opts{wasrunning}){
Ligne 568: Ligne 613:
     unlock_vm() unless ($opts{keeplock});     unlock_vm() unless ($opts{keeplock});
 } }
 + 
 # Remove the dumps # Remove the dumps
 sub run_cleanup{ sub run_cleanup{
Ligne 577: Ligne 622:
     print "$cnt file(s) removed\n" if $opts{debug};     print "$cnt file(s) removed\n" if $opts{debug};
 } }
 + 
 sub usage{ sub usage{
     print "usage:\n$0 --dump|--cleanup --vm=name[,vm2,vm3] [--debug] [--exclude=hda,hdb] [--compress] ".     print "usage:\n$0 --dump|--cleanup --vm=name[,vm2,vm3] [--debug] [--exclude=hda,hdb] [--compress] ".
Ligne 604: Ligne 649:
     "\t--snapsize=<snapsize>: The amount of space to use for snapshots. Use the same format as -L option of lvcreate. " .     "\t--snapsize=<snapsize>: The amount of space to use for snapshots. Use the same format as -L option of lvcreate. " .
         "eg: --snapsize=15G. Default is 5G\n\n" .         "eg: --snapsize=15G. Default is 5G\n\n" .
-    "\t--compress[=[gzip|bzip2|pbzip2|lzop|xz]]: On the fly compress the disks images during the dump. If you " .+    "\t--compress[=[gzip|bzip2|pbzip2|lzop|xz|lzip|plzip]]: On the fly compress the disks images during the dump. If you " .
         "don't specify a compression algo, gzip will be used.\n\n" .         "don't specify a compression algo, gzip will be used.\n\n" .
     "\t--exclude=hda,hdb: Prevent the disks listed from being dumped. The names are from the VM perspective, as " .     "\t--exclude=hda,hdb: Prevent the disks listed from being dumped. The names are from the VM perspective, as " .
Ligne 618: Ligne 663:
         "bs option of dd\n\n"         "bs option of dd\n\n"
 } }
 + 
 # Save a running VM, if it's running # Save a running VM, if it's running
 sub save_vm_state{ sub save_vm_state{
-    if (is_active()){+    if ($dom->is_active()){
         print "$vm is running, saving state....\n" if ($opts{debug});         print "$vm is running, saving state....\n" if ($opts{debug});
         $dom->save("$opts{backupdir}/$vm.state");         $dom->save("$opts{backupdir}/$vm.state");
Ligne 630: Ligne 675:
     }     }
 } }
 + 
 # Restore the state of a VM # Restore the state of a VM
 sub restore_vm{ sub restore_vm{
-    if (! is_active()){+    if (! $dom->is_active()){
         if (-e "$opts{backupdir}/$vm.state"){         if (-e "$opts{backupdir}/$vm.state"){
             print "\nTrying to restore $vm from $opts{backupdir}/$vm.state\n" if ($opts{debug});             print "\nTrying to restore $vm from $opts{backupdir}/$vm.state\n" if ($opts{debug});
Ligne 639: Ligne 684:
             print "Waiting for restoration to complete\n" if ($opts{debug});             print "Waiting for restoration to complete\n" if ($opts{debug});
             my $i = 0;             my $i = 0;
-            while ((!is_active()) && ($i < 120)){+            while ((!$dom->is_active()) && ($i < 120)){
                 sleep(5);                 sleep(5);
                 $i = $i+5;                 $i = $i+5;
Ligne 655: Ligne 700:
     }     }
 } }
 + 
 # Suspend a VM # Suspend a VM
 sub suspend_vm(){ sub suspend_vm(){
-    if (is_active()){+    if ($dom->is_active()){
         print "$vm is running, suspending\n" if ($opts{debug});         print "$vm is running, suspending\n" if ($opts{debug});
         $dom->suspend();         $dom->suspend();
Ligne 667: Ligne 712:
     }     }
 } }
 + 
 # Resume a VM if it's paused # Resume a VM if it's paused
 sub resume_vm(){ sub resume_vm(){
Ligne 679: Ligne 724:
     }     }
 } }
 + 
 # Dump the domain description as XML # Dump the domain description as XML
 sub save_xml{ sub save_xml{
Ligne 687: Ligne 732:
     close XML;     close XML;
 } }
 + 
 # Create an LVM snapshot # Create an LVM snapshot
 # Pass the original logical volume and the suffix # Pass the original logical volume and the suffix
Ligne 702: Ligne 747:
     return $ret;     return $ret;
 } }
 + 
 # Remove an LVM snapshot # Remove an LVM snapshot
 sub destroy_snapshot{ sub destroy_snapshot{
Ligne 713: Ligne 758:
     return $ret;     return $ret;
 } }
 + 
 # Lock a VM backup dir # Lock a VM backup dir
 # Just creates an empty lock file # Just creates an empty lock file
Ligne 726: Ligne 771:
 # Just removes the lock file # Just removes the lock file
 sub unlock_vm{ sub unlock_vm{
-    print "Removing lock file for $vm\n" if $opts{debug};+    print "Removing lock file for $vm\n\n" if $opts{debug};
     unlink <$opts{backupdir}/$vm.lock>;     unlink <$opts{backupdir}/$vm.lock>;
 } }
Ligne 742: Ligne 787:
   * pbzip2   * pbzip2
   * xz   * xz
 +  * lzip
 +  * plzip
  
  • tuto/virtualisation/virt_scripts.txt
  • Dernière modification: 12/07/2012 23:32
  • de dani