From: smckown Date: Thu, 10 Jan 2008 21:19:01 +0000 (+0000) Subject: Fix indents to 2 spaces at a time. X-Git-Tag: backuppc-ovz-0.1~11 X-Git-Url: https://oss.titaniummirror.com/gitweb?p=ovzbpc.git;a=commitdiff_plain;h=fe07358077e767579512761446b889a8159003ed Fix indents to 2 spaces at a time. --- diff --git a/BackupPC_ovz b/BackupPC_ovz index f85198a..7106749 100755 --- a/BackupPC_ovz +++ b/BackupPC_ovz @@ -25,39 +25,39 @@ my $snapsize = '1g'; sub cmdExecOrEval { - my($cmd, @args) = @_; - - if ( (ref($cmd) eq "ARRAY" ? $cmd->[0] : $cmd) =~ /^\&/ ) { - $cmd = join(" ", $cmd) if ( ref($cmd) eq "ARRAY" ); - eval($cmd); - print(STDERR "Perl code fragment for exec shouldn't return!!\n"); - exit(1); - } else { - $cmd = [split(/\s+/, $cmd)] if ( ref($cmd) ne "ARRAY" ); - alarm(0); - $cmd = [map { m/(.*)/ } @$cmd]; # untaint - # - # force list-form of exec(), ie: no shell even for 1 arg - # - exec { $cmd->[0] } @$cmd; - print(STDERR "Exec failed for @$cmd\n"); - exit(1); - } + my($cmd, @args) = @_; + + if ( (ref($cmd) eq "ARRAY" ? $cmd->[0] : $cmd) =~ /^\&/ ) { + $cmd = join(" ", $cmd) if ( ref($cmd) eq "ARRAY" ); + eval($cmd); + print(STDERR "Perl code fragment for exec shouldn't return!!\n"); + exit(1); + } else { + $cmd = [split(/\s+/, $cmd)] if ( ref($cmd) ne "ARRAY" ); + alarm(0); + $cmd = [map { m/(.*)/ } @$cmd]; # untaint + # + # force list-form of exec(), ie: no shell even for 1 arg + # + exec { $cmd->[0] } @$cmd; + print(STDERR "Exec failed for @$cmd\n"); + exit(1); + } } # FIXME: this guy sometimes needs to use /dev/null as stdin, stdout and stderr # so that it doesn't pollute the stream back to the backup server. sub cmdSystemOrEval { - my($cmd, @args) = @_; - - $? = 0; - $cmd = join(" ", $cmd) if ( ref($cmd) eq "ARRAY" ); - if ( (ref($cmd) eq "ARRAY" ? $cmd->[0] : $cmd) =~ /^\&/ ) { - eval($cmd); - } else { - system($cmd); - } + my($cmd, @args) = @_; + + $? = 0; + $cmd = join(" ", $cmd) if ( ref($cmd) eq "ARRAY" ); + if ( (ref($cmd) eq "ARRAY" ? $cmd->[0] : $cmd) =~ /^\&/ ) { + eval($cmd); + } else { + system($cmd); + } } # To be called by the BackupPC server in a preuser script. These are the @@ -65,511 +65,509 @@ sub cmdSystemOrEval # client invocation -- will cause the backup to hang indefinitely. sub refreshConfig() { - # Write the VEs on all HNs to a config file on the BackupPC server for - # later use. - open my $out, ">/etc/backuppc/vzlist_bpc" || - die "Cannot write to /etc/backuppc/vzlist_bpc"; - foreach my $hn (@HNS) { - open my $fh, "ssh -l root $hn vzlist -a |" || - die "Can run remote vzlist command"; - while (<$fh>) { - chomp; - my ($veid, $junk, $running, $junk, $hostname) = split(' '); - if ($veid =~ /[0-9]+/ && $hostname ne '-') { - if ($running eq "running") { - $running = 1; - } else { - $running = 0; - } - print $out "$hostname,$veid,$hn,$running\n"; - } + # Write the VEs on all HNs to a config file on the BackupPC server for + # later use. + open my $out, ">/etc/backuppc/vzlist_bpc" || + die "Cannot write to /etc/backuppc/vzlist_bpc"; + foreach my $hn (@HNS) { + open my $fh, "ssh -l root $hn vzlist -a |" || + die "Can run remote vzlist command"; + while (<$fh>) { + chomp; + my ($veid, $junk, $running, $junk, $hostname) = split(' '); + if ($veid =~ /[0-9]+/ && $hostname ne '-') { + if ($running eq "running") { + $running = 1; + } else { + $running = 0; } - close($fh); - } - close($out); - - # Copy the script to the HNs - my $remoteCmd = "/usr/bin/".basename($0); - foreach my $hn (@HNS) { - my $cmd = "rsync -aq -e ssh $0 root\@$hn:$remoteCmd"; - #print "Executing '$cmd'\n"; - cmdSystemOrEval($cmd); + print $out "$hostname,$veid,$hn,$running\n"; + } } + close($fh); + } + close($out); + + # Copy the script to the HNs + my $remoteCmd = "/usr/bin/".basename($0); + foreach my $hn (@HNS) { + my $cmd = "rsync -aq -e ssh $0 root\@$hn:$remoteCmd"; + #print "Executing '$cmd'\n"; + cmdSystemOrEval($cmd); + } } # For use on the BackupPC server. sub loadVeList() { - open my $fh, ") { - chomp; - my ($hostname, $veid, $host, $running) = split(','); - push(@velist, { - "hostname" => $hostname, - "VEID" => $veid, - "HN" => $host, - "running" => $running - }); - } - close($fh); + open my $fh, ") { + chomp; + my ($hostname, $veid, $host, $running) = split(','); + push(@velist, { + "hostname" => $hostname, + "VEID" => $veid, + "HN" => $host, + "running" => $running + }); + } + close($fh); } # For use on the HN sub localVe($) { - my ($veid) = @_; - die "HN: no veid" if (!defined($veid)); - - my $vzdir = '/etc/vz'; - die "HN is not running OpenVZ" if (!defined($vzdir)); - - my $lockdir = undef; - my $dumpdir = undef; - my $private = undef; - my $root = undef; - open my $fh, "<$vzdir/vz.conf" || die "Cannot open $vzdir/vz.conf"; - while (<$fh>) { - chomp; - my ($name, $value) = split('='); - if ($name eq 'LOCKDIR') { - $lockdir = $value; - die "OpenVZ LOCKDIR ($lockdir) is invalid" if (! -d $lockdir); - } elsif ($name eq 'DUMPDIR') { - $dumpdir = $value; - die "OpenVZ DUMPDIR ($dumpdir) is invalid" if (! -d $dumpdir); - } elsif ($name eq 'VE_PRIVATE') { - $private = $value; - } elsif ($name eq 'VE_ROOT') { - $root = $value; - } + my ($veid) = @_; + die "HN: no veid" if (!defined($veid)); + + my $vzdir = '/etc/vz'; + die "HN is not running OpenVZ" if (!defined($vzdir)); + + my $lockdir = undef; + my $dumpdir = undef; + my $private = undef; + my $root = undef; + open my $fh, "<$vzdir/vz.conf" || die "Cannot open $vzdir/vz.conf"; + while (<$fh>) { + chomp; + my ($name, $value) = split('='); + if ($name eq 'LOCKDIR') { + $lockdir = $value; + die "OpenVZ LOCKDIR ($lockdir) is invalid" if (! -d $lockdir); + } elsif ($name eq 'DUMPDIR') { + $dumpdir = $value; + die "OpenVZ DUMPDIR ($dumpdir) is invalid" if (! -d $dumpdir); + } elsif ($name eq 'VE_PRIVATE') { + $private = $value; + } elsif ($name eq 'VE_ROOT') { + $root = $value; } - close($fh); - - my $confdir = "$vzdir/conf"; - die "OpenVZ conf dir ($confdir) not found" if (! -d $confdir); - - my $hostname = undef; - my $conffile = "$confdir/$veid.conf"; - open $fh, "<$conffile" || die "Cannot open $conffile"; - while (<$fh>) { - chomp; - my ($name, $value) = split('='); - $private = $value if ($name eq 'VE_PRIVATE'); - $root = $value if ($name eq 'VE_ROOT'); - if ($name eq 'HOSTNAME') { - $value =~ s/"//g; - $hostname = gethostbyaddr(gethostbyname($value), AF_INET); - } + } + close($fh); + + my $confdir = "$vzdir/conf"; + die "OpenVZ conf dir ($confdir) not found" if (! -d $confdir); + + my $hostname = undef; + my $conffile = "$confdir/$veid.conf"; + open $fh, "<$conffile" || die "Cannot open $conffile"; + while (<$fh>) { + chomp; + my ($name, $value) = split('='); + $private = $value if ($name eq 'VE_PRIVATE'); + $root = $value if ($name eq 'VE_ROOT'); + if ($name eq 'HOSTNAME') { + $value =~ s/"//g; + $hostname = gethostbyaddr(gethostbyname($value), AF_INET); } - close($fh); - - $private =~ s/"//g; - $private =~ s|/\$VEID|/$veid|g; - die "VE_PRIVATE is not defined" if (!defined($private)); - die "VE $veid private dir ($private) not found" if (! -d $private); - - $root =~ s|/\$VEID|/$veid|g; - $root =~ s/"//g; - die "VE_ROOT is not defined" if (!defined($root)); - die "VE $veid root dir ($root) not found" if (! -d $root); - - die "VE $veid has no HOSTNAME" if (!defined($hostname)); - - my $status = `vzctl status $veid`; - my $running = 0; - $running = 1 if ($status =~ /running/); - - return { - "vzdir" => $vzdir, - "lockdir" => $lockdir, - "dumpdir" => $dumpdir, - "confdir" => $confdir, - "conffile" => $conffile, - "private" => $private, - "root" => $root, - "hostname" => $hostname, - "VEID" => $veid, - "running" => $running - }; + } + close($fh); + + $private =~ s/"//g; + $private =~ s|/\$VEID|/$veid|g; + die "VE_PRIVATE is not defined" if (!defined($private)); + die "VE $veid private dir ($private) not found" if (! -d $private); + + $root =~ s|/\$VEID|/$veid|g; + $root =~ s/"//g; + die "VE_ROOT is not defined" if (!defined($root)); + die "VE $veid root dir ($root) not found" if (! -d $root); + + die "VE $veid has no HOSTNAME" if (!defined($hostname)); + + my $status = `vzctl status $veid`; + my $running = 0; + $running = 1 if ($status =~ /running/); + + return { + "vzdir" => $vzdir, + "lockdir" => $lockdir, + "dumpdir" => $dumpdir, + "confdir" => $confdir, + "conffile" => $conffile, + "private" => $private, + "root" => $root, + "hostname" => $hostname, + "VEID" => $veid, + "running" => $running + }; } sub getVeEntry($$) { - my ($field, $arg) = @_; - for (my $i = 0; $i <= $#velist; $i++) { - my $ve = ${\$velist[$i]}; - return $ve if ($ve->{$field} eq $arg); - } - return undef; + my ($field, $arg) = @_; + for (my $i = 0; $i <= $#velist; $i++) { + my $ve = ${\$velist[$i]}; + return $ve if ($ve->{$field} eq $arg); + } + return undef; } sub getVeByHostname($) { - my ($host) = @_; + my ($host) = @_; - my $hostname = gethostbyaddr(gethostbyname($host), AF_INET); - die "Host $host not found" if (!defined($hostname)); + my $hostname = gethostbyaddr(gethostbyname($host), AF_INET); + die "Host $host not found" if (!defined($hostname)); - my $ve = getVeEntry('hostname', $hostname); - die "Host $hostname is not a VE" if (!defined($ve)); - return $ve; + my $ve = getVeEntry('hostname', $hostname); + die "Host $hostname is not a VE" if (!defined($ve)); + return $ve; } sub getVeEntries($$) { - my ($field, $host) = @_; - my @entries; - - for (my $i = 0; $i <= $#velist; $i++) { - my $ve = ${\$velist[$i]}; - push(@entries, $ve) if ($ve->{$field} eq $host); - } - return @entries; + my ($field, $host) = @_; + my @entries; + + for (my $i = 0; $i <= $#velist; $i++) { + my $ve = ${\$velist[$i]}; + push(@entries, $ve) if ($ve->{$field} eq $host); + } + return @entries; } sub printVeEntry($) { - my ($ve) = @_; - - die "No VE to print" if (!defined($ve)); - print STDERR '{ '; - #foreach my $k (keys %{$velist[0]}) { - foreach my $k (keys %{$ve}) { - print STDERR $k.' => '.$ve->{$k}."\n "; - } - print STDERR "}\n"; + my ($ve) = @_; + + die "No VE to print" if (!defined($ve)); + print STDERR '{ '; + #foreach my $k (keys %{$velist[0]}) { + foreach my $k (keys %{$ve}) { + print STDERR $k.' => '.$ve->{$k}."\n "; + } + print STDERR "}\n"; } sub delSnapshot($) { - my ($ve) = @_; - die "No VE record for delSnapshot" if (!defined($ve)); - - #print "delSnapshot: doing nothing for now\n"; - #printVeEntry($ve); - #return; - - my $dir = $ve->{'snaproot'}; - if (defined($dir) && -d $dir) { - #cmdSystemOrEval("rm -rf $dir/etc/vzdump"); - cmdSystemOrEval("umount $dir"); - cmdSystemOrEval("rmdir $dir"); - } - - my $dev = $ve->{'snapdev'}; - cmdSystemOrEval("lvremove -f $dev >/dev/null 2>&1") if (-b $dev); + my ($ve) = @_; + die "No VE record for delSnapshot" if (!defined($ve)); + + #print "delSnapshot: doing nothing for now\n"; + #printVeEntry($ve); + #return; + + my $dir = $ve->{'snaproot'}; + if (defined($dir) && -d $dir) { + #cmdSystemOrEval("rm -rf $dir/etc/vzdump"); + cmdSystemOrEval("umount $dir"); + cmdSystemOrEval("rmdir $dir"); + } + + my $dev = $ve->{'snapdev'}; + cmdSystemOrEval("lvremove -f $dev >/dev/null 2>&1") if (-b $dev); } sub getDevice($) { - my ($dir) = @_; - - open my $fh, "df -P '$dir'|" || die "Unable to exec df"; - <$fh>; # skip header - my $df = <$fh>; - close($fh); - chomp($df); - my ($dev, $junk, $junk, $junk, $junk, $mpoint) = split (/\s+/, $df); - - my $vg = undef; - my $lv = undef; - open $fh, "lvscan|" || die "Unable to exec lvscan"; - while (my $line = <$fh>) { - if ($line =~ m|^\s+ACTIVE\s+\'/dev/([^/]+)/([^\']+)\'\s|) { - # vg is $1, lv is $2 - if ($dev eq "/dev/$1/$2" || $dev eq "/dev/mapper/$1-$2") { - $vg = $1; - $lv = $2; - } - } + my ($dir) = @_; + + open my $fh, "df -P '$dir'|" || die "Unable to exec df"; + <$fh>; # skip header + my $df = <$fh>; + close($fh); + chomp($df); + my ($dev, $junk, $junk, $junk, $junk, $mpoint) = split (/\s+/, $df); + + my $vg = undef; + my $lv = undef; + open $fh, "lvscan|" || die "Unable to exec lvscan"; + while (my $line = <$fh>) { + if ($line =~ m|^\s+ACTIVE\s+\'/dev/([^/]+)/([^\']+)\'\s|) { + # vg is $1, lv is $2 + if ($dev eq "/dev/$1/$2" || $dev eq "/dev/mapper/$1-$2") { + $vg = $1; + $lv = $2; + } } - close($fh); + } + close($fh); - die "Device $dev has no LVM entry for volume group" if (!defined($vg)); - die "Device $dev has no LVM entry for logical volume" if (!defined($lv)); - return ($dev, $mpoint, $vg, $lv); + die "Device $dev has no LVM entry for volume group" if (!defined($vg)); + die "Device $dev has no LVM entry for logical volume" if (!defined($lv)); + return ($dev, $mpoint, $vg, $lv); } sub makeSnapshot($) { - my ($ve) = @_; - die "No VE record for snapshot" if (!defined($ve)); - - my ($dev, $lvmpath, $vg, $lv) = getDevice($ve->{'private'}); - #print "snapshot: dev=$dev, lvmpath=$lvmpath, vg=$vg, lm=$lv\n"; - die "Can't find device for VE filesystem" if (!defined($dev)); - - my $snaproot = "/$vzsnap"; - - mkpath "$snaproot" || - die "Can't create snapshot directory (backup in progress?)"; - $ve->{'snaproot'} = $snaproot; - - my $snapdev = "/dev/$vg/$vzsnap"; - die "Snapshot dev $snapdev exists (backup in progress?)" if (-b $snapdev); - # FIXME: xfs_freeze hangs; without it we are likely to fail at some point. - # FIXME: finding the mount point instead of hard coding. - #cmdSystemOrEval("xfs_freeze -f /var/lib/vz/private"); - cmdSystemOrEval("lvcreate --size $snapsize --snapshot --name $vzsnap /dev/$vg/$lv >/dev/null 2>&1"); - #cmdSystemOrEval("xfs_freeze -u /var/lib/vz/private"); - if (! -b $snapdev) { - delSnapshot($ve); - die "Failed to create snapshot device" - } - $ve->{'snapdev'} = $snapdev; - cmdSystemOrEval("mount -o nouuid $snapdev $snaproot"); - - my $snapprivate = $ve->{'private'}; - $snapprivate =~ s|/?$lvmpath/?|/$vzsnap/|; - #print "snapshot: snapprivate = $snapprivate\n"; - if ($snapprivate !~ /$vzsnap/ || ! -d $snapprivate) { - delSnapshot($ve); - die "Wrong lvm mount point $lvmpath"; - } - $ve->{'snapprivate'} = $snapprivate; - - if (! -d "/$snapprivate/etc") { - delSnapshot($ve); - die "Mount failure or filesystem doesn't belong to a VE"; - } + my ($ve) = @_; + die "No VE record for snapshot" if (!defined($ve)); + + my ($dev, $lvmpath, $vg, $lv) = getDevice($ve->{'private'}); + #print "snapshot: dev=$dev, lvmpath=$lvmpath, vg=$vg, lm=$lv\n"; + die "Can't find device for VE filesystem" if (!defined($dev)); + + my $snaproot = "/$vzsnap"; + + mkpath "$snaproot" || + die "Can't create snapshot directory (backup in progress?)"; + $ve->{'snaproot'} = $snaproot; + + my $snapdev = "/dev/$vg/$vzsnap"; + die "Snapshot dev $snapdev exists (backup in progress?)" if (-b $snapdev); + # FIXME: xfs_freeze hangs; without it we are likely to fail at some point. + # FIXME: finding the mount point instead of hard coding. + #cmdSystemOrEval("xfs_freeze -f /var/lib/vz/private"); + cmdSystemOrEval("lvcreate --size $snapsize --snapshot --name $vzsnap /dev/$vg/$lv >/dev/null 2>&1"); + #cmdSystemOrEval("xfs_freeze -u /var/lib/vz/private"); + if (! -b $snapdev) { + delSnapshot($ve); + die "Failed to create snapshot device" + } + $ve->{'snapdev'} = $snapdev; + cmdSystemOrEval("mount -o nouuid $snapdev $snaproot"); + + my $snapprivate = $ve->{'private'}; + $snapprivate =~ s|/?$lvmpath/?|/$vzsnap/|; + #print "snapshot: snapprivate = $snapprivate\n"; + if ($snapprivate !~ /$vzsnap/ || ! -d $snapprivate) { + delSnapshot($ve); + die "Wrong lvm mount point $lvmpath"; + } + $ve->{'snapprivate'} = $snapprivate; + + if (! -d "/$snapprivate/etc") { + delSnapshot($ve); + die "Mount failure or filesystem doesn't belong to a VE"; + } } sub saveConfigs($) { - my ($ve) = @_; - die "No VE record for saveConfigs" if (!defined($ve)); - - # Copy configuration and other scripts belonging to VE into VE's snapshot - my $snapprivate = $ve->{'snapprivate'}; - mkpath "$snapprivate/etc/vzdump"; - my $conffile = $ve->{'conffile'}; - cmdSystemOrEval("cp $conffile $snapprivate/etc/vzdump/vps.conf"); - foreach my $ext (@script_ext) { - my $fn = $ve->{'confdir'}."/".$ve->{'VEID'}.".$ext"; - cmdSystemOrEval("cp $fn $snapprivate/etc/vzdump/vps.$ext") if (-f $fn); - } + my ($ve) = @_; + die "No VE record for saveConfigs" if (!defined($ve)); + + # Copy configuration and other scripts belonging to VE into VE's snapshot + my $snapprivate = $ve->{'snapprivate'}; + mkpath "$snapprivate/etc/vzdump"; + my $conffile = $ve->{'conffile'}; + cmdSystemOrEval("cp $conffile $snapprivate/etc/vzdump/vps.conf"); + foreach my $ext (@script_ext) { + my $fn = $ve->{'confdir'}."/".$ve->{'VEID'}.".$ext"; + cmdSystemOrEval("cp $fn $snapprivate/etc/vzdump/vps.$ext") if (-f $fn); + } } sub restoreConfigs($) { - my ($ve) = @_; - die "No VE record for restoreConfigs" if (!defined($ve)); - - my $private = $ve->{'private'}; - die "Can't restore invalid private dir $private" if (! -d $private); - my $qprivate = $private; - $qprivate =~ s|/|\\\/|g; - $qprivate =~ s|/$ve->{'VEID'}$|/\$VEID|; - - my $root = $ve->{'root'}; - die "Can't restore invalid root dir $root" if (! -d $root); - my $qroot = $root; - $qroot =~ s|/|\\\/|g; - $qroot =~ s|/$ve->{'VEID'}$|/\$VEID|; - - my $conffile = $ve->{'conffile'}; - my $cmd = "sed -e 's/VE_ROOT=.*/VE_ROOT=\\\"$qroot\\\"/' -e 's/VE_PRIVATE=.*/VE_PRIVATE=\\\"$qprivate\\\"/' <'$private/etc/vzdump/vps.conf' >'$conffile'"; - cmdSystemOrEval($cmd); - - foreach my $s (@script_ext) { - my $cfgdir = $ve->{'confdir'}; - my $src = $ve->{'private'}."/etc/vzdump/vps.$s"; - my $dest = "$cfgdir/".$ve->{'VEID'}.".$s"; - cmdSystemOrEval("mv '$src' '$dest'") if (-f $src); - } - - rmtree "$private/etc/vzdump"; - - # FIXME: on error, if there was no private dir to start, we should - # remove everything we added.? + my ($ve) = @_; + die "No VE record for restoreConfigs" if (!defined($ve)); + + my $private = $ve->{'private'}; + die "Can't restore invalid private dir $private" if (! -d $private); + my $qprivate = $private; + $qprivate =~ s|/|\\\/|g; + $qprivate =~ s|/$ve->{'VEID'}$|/\$VEID|; + + my $root = $ve->{'root'}; + die "Can't restore invalid root dir $root" if (! -d $root); + my $qroot = $root; + $qroot =~ s|/|\\\/|g; + $qroot =~ s|/$ve->{'VEID'}$|/\$VEID|; + + my $conffile = $ve->{'conffile'}; + my $cmd = "sed -e 's/VE_ROOT=.*/VE_ROOT=\\\"$qroot\\\"/' -e 's/VE_PRIVATE=.*/VE_PRIVATE=\\\"$qprivate\\\"/' <'$private/etc/vzdump/vps.conf' >'$conffile'"; + cmdSystemOrEval($cmd); + + foreach my $s (@script_ext) { + my $cfgdir = $ve->{'confdir'}; + my $src = $ve->{'private'}."/etc/vzdump/vps.$s"; + my $dest = "$cfgdir/".$ve->{'VEID'}.".$s"; + cmdSystemOrEval("mv '$src' '$dest'") if (-f $src); + } + + rmtree "$private/etc/vzdump"; + + # FIXME: on error, if there was no private dir to start, we should + # remove everything we added.? } sub checkRunningClient() { - die "A backup or restore operation are already in progress" - if (Proc::PID::File->running({ dir => '/tmp', verify => 1 })); - - # Clean up any prior backup's mount point and snapshot, if it exists. - # Note that the snapshot is small, so we don't really want it lying around! - my $vg = undef; - open my $fh, "lvscan|" || die "Unable to exec lvscan"; - while (my $line = <$fh>) { - if ($line =~ m|^\s+ACTIVE\s+Snapshot\s+\'/dev/([^/]+)/$vzsnap\'\s|) { - $vg = $1; - } - } - close($fh); - if (defined($vg)) { - my $dev = "/dev/mapper/$vg-$vzsnap"; - #print "Found vzsnap lv $dev\n"; - cmdSystemOrEval("umount /$vzsnap"); - cmdSystemOrEval("rmdir /$vzsnap") if (-d "/$vzsnap"); - cmdSystemOrEval("lvremove -f $dev >/dev/null 2>&1") if (-b $dev); + die "A backup or restore operation are already in progress" + if (Proc::PID::File->running({ dir => '/tmp', verify => 1 })); + + # Clean up any prior backup's mount point and snapshot, if it exists. + # Note that the snapshot is small, so we don't really want it lying around! + my $vg = undef; + open my $fh, "lvscan|" || die "Unable to exec lvscan"; + while (my $line = <$fh>) { + if ($line =~ m|^\s+ACTIVE\s+Snapshot\s+\'/dev/([^/]+)/$vzsnap\'\s|) { + $vg = $1; } + } + close($fh); + if (defined($vg)) { + my $dev = "/dev/mapper/$vg-$vzsnap"; + #print "Found vzsnap lv $dev\n"; + cmdSystemOrEval("umount /$vzsnap"); + cmdSystemOrEval("rmdir /$vzsnap") if (-d "/$vzsnap"); + cmdSystemOrEval("lvremove -f $dev >/dev/null 2>&1") if (-b $dev); + } } sub runClient($) { - my ($restore) = @_; - - checkRunningClient(); - - my $veid = shift(@ARGV); - die "HN needs a VEID argument" if (!defined($veid)); - die "HN: no command to execute after VEID" if ($#ARGV < 0); - - # Find $host in the list of VEs - my $ve = localVe($veid); - die "VE $veid not found on this HN" if (!defined($ve)); - #printVeEntry($ve); - - if (! $restore) { - cmdSystemOrEval("vzctl stop $veid >/dev/null 2>&1") - if ($ve->{'running'}); - makeSnapshot($ve); - cmdSystemOrEval("vzctl start $veid >/dev/null 2>&1") - if ($ve->{'running'}); - die "Failed to make snapshot of filesystem for VE $veid" - if (!defined($ve->{'snaproot'})); - - # Make and exec the backup command. Do it in a chroot to the snapshot - # of the VE's root dir so that any relative path information in the - # backup command is accurate. This does mean that each VE needs rsync, - # etc. - my $cmd = "chroot ".$ve->{'snapprivate'}." ".join(' ', @ARGV); - #print "HN: cmd |$cmd|\n"; - $? = 0; - cmdSystemOrEval($cmd); - my $ret = $?; # FIXME - - # Remove snapshot, we're done - delSnapshot($ve); - - # Pass the return code back - #exit $ret; FIXME: currently, cmdSystemOrEval doesn't return a retcode. - exit 0; - } else { - # Restores work off the VE's live root filesystem. A full restore - # should be done to the HN host, redirecting the restore to the VE's - # private directory on the HN when the VE is stopped. - my $cmd = "chroot ".$ve->{'private'}." ".join(' ', @ARGV); - #print "HN: cmd |$cmd|\n"; - # A restore can exec, because we have no cleanup to do. - cmdExecOrEval($cmd); - } + my ($restore) = @_; + + checkRunningClient(); + + my $veid = shift(@ARGV); + die "HN needs a VEID argument" if (!defined($veid)); + die "HN: no command to execute after VEID" if ($#ARGV < 0); + + # Find $host in the list of VEs + my $ve = localVe($veid); + die "VE $veid not found on this HN" if (!defined($ve)); + #printVeEntry($ve); + + if (! $restore) { + cmdSystemOrEval("vzctl stop $veid >/dev/null 2>&1") if ($ve->{'running'}); + makeSnapshot($ve); + cmdSystemOrEval("vzctl start $veid >/dev/null 2>&1") if ($ve->{'running'}); + die "Failed to make snapshot of filesystem for VE $veid" + if (!defined($ve->{'snaproot'})); + + # Make and exec the backup command. Do it in a chroot to the snapshot + # of the VE's root dir so that any relative path information in the + # backup command is accurate. This does mean that each VE needs rsync, + # etc. + my $cmd = "chroot ".$ve->{'snapprivate'}." ".join(' ', @ARGV); + #print "HN: cmd |$cmd|\n"; + $? = 0; + cmdSystemOrEval($cmd); + my $ret = $?; # FIXME + + # Remove snapshot, we're done + delSnapshot($ve); + + # Pass the return code back + #exit $ret; FIXME: currently, cmdSystemOrEval doesn't return a retcode. + exit 0; + } else { + # Restores work off the VE's live root filesystem. A full restore + # should be done to the HN host, redirecting the restore to the VE's + # private directory on the HN when the VE is stopped. + my $cmd = "chroot ".$ve->{'private'}." ".join(' ', @ARGV); + #print "HN: cmd |$cmd|\n"; + # A restore can exec, because we have no cleanup to do. + cmdExecOrEval($cmd); + } } sub runServer($) { - my ($restore) = @_; - - # Build the beginning remote command - my $remoteCmd = "/usr/bin/".basename($0); - #print "Remote command is $remoteCmd\n"; - - my $host = shift(@ARGV); - die "Hostname argument required" if (!defined($host)); - die "No command to execute after hostname" if ($#ARGV < 0); - - # Find $host in the list of VEs - loadVeList(); - my $ve = getVeByHostname($host); - die "VE $host not found" if (!defined($ve)); - #printVeEntry($ve); - - # The command line is bisected by the next occurrence of $host. Everything - # before is the ssh command (sans what to run on the VE) and everything - # after is the xfer command to run on the VE. - my @sshCmd; - my @xferCmd; - my $foundHost = 0; - foreach my $arg (@ARGV) { - if ($arg eq $host) { - $foundHost = 1; - } else { - if ($foundHost) { - push(@xferCmd, $arg); - } else { - push(@sshCmd, $arg); - } - } + my ($restore) = @_; + + # Build the beginning remote command + my $remoteCmd = "/usr/bin/".basename($0); + #print "Remote command is $remoteCmd\n"; + + my $host = shift(@ARGV); + die "Hostname argument required" if (!defined($host)); + die "No command to execute after hostname" if ($#ARGV < 0); + + # Find $host in the list of VEs + loadVeList(); + my $ve = getVeByHostname($host); + die "VE $host not found" if (!defined($ve)); + #printVeEntry($ve); + + # The command line is bisected by the next occurrence of $host. Everything + # before is the ssh command (sans what to run on the VE) and everything + # after is the xfer command to run on the VE. + my @sshCmd; + my @xferCmd; + my $foundHost = 0; + foreach my $arg (@ARGV) { + if ($arg eq $host) { + $foundHost = 1; + } else { + if ($foundHost) { + push(@xferCmd, $arg); + } else { + push(@sshCmd, $arg); + } } - die "No ssh command found" if ($#sshCmd < 0); - die "No xfer command found" if ($#xferCmd < 0); - #print "ssh command: |".join(' ', @sshCmd)."|\n"; - #print "xfer command: |".join(' ', @xferCmd)."|\n"; - - # Create command line to initiate the remote side of the backup. The - # remote side runs on the VE's HN and is given the VE's VEID. - my $cmd = join(' ', @sshCmd)." ".$ve->{'HN'}." $remoteCmd ". - ($restore ? "restore " : "").$ve->{'VEID'}." ".join(' ', @xferCmd); - #print "remote command: |$cmd|\n"; - - ## Search and replace - #foreach my $key (keys %{$velist[0]}) { - # my $val = $ve->{$key}; - # $cmd =~ s/\@$key\@/$val/g if (defined($val)); - #} - - cmdExecOrEval($cmd); + } + die "No ssh command found" if ($#sshCmd < 0); + die "No xfer command found" if ($#xferCmd < 0); + #print "ssh command: |".join(' ', @sshCmd)."|\n"; + #print "xfer command: |".join(' ', @xferCmd)."|\n"; + + # Create command line to initiate the remote side of the backup. The + # remote side runs on the VE's HN and is given the VE's VEID. + my $cmd = join(' ', @sshCmd)." ".$ve->{'HN'}." $remoteCmd ". + ($restore ? "restore " : "").$ve->{'VEID'}." ".join(' ', @xferCmd); + #print "remote command: |$cmd|\n"; + + ## Search and replace + #foreach my $key (keys %{$velist[0]}) { + # my $val = $ve->{$key}; + # $cmd =~ s/\@$key\@/$val/g if (defined($val)); + #} + + cmdExecOrEval($cmd); } # A hard-coded test; didn't seem to help sub runServer_test($) { - my ($restore) = @_; - - # Build the beginning remote command - my $remoteCmd = "/usr/bin/".basename($0); - #print "Remote command is $remoteCmd\n"; - - my $host = shift(@ARGV); - die "Hostname argument required" if (!defined($host)); - die "No command to execute after hostname" if ($#ARGV < 0); - - # Find $host in the list of VEs - loadVeList(); - my $ve = getVeByHostname($host); - die "VE $host not found" if (!defined($ve)); - #printVeEntry($ve); - - # The command line is bisected by the next occurrence of $host. Everything - # before is the ssh command (sans what to run on the VE) and everything - # after is the xfer command to run on the VE. - my @sshCmd; - my @xferCmd; - my $foundHost = 0; - foreach my $arg (@ARGV) { - if ($arg eq $host) { - $foundHost = 1; - } else { - if ($foundHost) { - push(@xferCmd, $arg); - } else { - push(@sshCmd, $arg); - } - } + my ($restore) = @_; + + # Build the beginning remote command + my $remoteCmd = "/usr/bin/".basename($0); + #print "Remote command is $remoteCmd\n"; + + my $host = shift(@ARGV); + die "Hostname argument required" if (!defined($host)); + die "No command to execute after hostname" if ($#ARGV < 0); + + # Find $host in the list of VEs + loadVeList(); + my $ve = getVeByHostname($host); + die "VE $host not found" if (!defined($ve)); + #printVeEntry($ve); + + # The command line is bisected by the next occurrence of $host. Everything + # before is the ssh command (sans what to run on the VE) and everything + # after is the xfer command to run on the VE. + my @sshCmd; + my @xferCmd; + my $foundHost = 0; + foreach my $arg (@ARGV) { + if ($arg eq $host) { + $foundHost = 1; + } else { + if ($foundHost) { + push(@xferCmd, $arg); + } else { + push(@sshCmd, $arg); + } } - die "No ssh command found" if ($#sshCmd < 0); - die "No xfer command found" if ($#xferCmd < 0); - #print "ssh command: |".join(' ', @sshCmd)."|\n"; - #print "xfer command: |".join(' ', @xferCmd)."|\n"; - - # Create command line to initiate the remote side of the backup. The - # remote side runs on the VE's HN and is given the VE's VEID. - my $cmd = join(' ', @sshCmd)." pe18002.titaniummirror.com $remoteCmd ". - ($restore ? "restore " : "")."151 ".join(' ', @xferCmd); - #print "remote command: |$cmd|\n"; - - ## Search and replace - #foreach my $key (keys %{$velist[0]}) { - # my $val = $ve->{$key}; - # $cmd =~ s/\@$key\@/$val/g if (defined($val)); - #} - - cmdExecOrEval($cmd); + } + die "No ssh command found" if ($#sshCmd < 0); + die "No xfer command found" if ($#xferCmd < 0); + #print "ssh command: |".join(' ', @sshCmd)."|\n"; + #print "xfer command: |".join(' ', @xferCmd)."|\n"; + + # Create command line to initiate the remote side of the backup. The + # remote side runs on the VE's HN and is given the VE's VEID. + my $cmd = join(' ', @sshCmd)." pe18002.titaniummirror.com $remoteCmd ". + ($restore ? "restore " : "")."151 ".join(' ', @xferCmd); + #print "remote command: |$cmd|\n"; + + ## Search and replace + #foreach my $key (keys %{$velist[0]}) { + # my $val = $ve->{$key}; + # $cmd =~ s/\@$key\@/$val/g if (defined($val)); + #} + + cmdExecOrEval($cmd); } ## MAIN @@ -578,27 +576,27 @@ sub runServer_test($) # options server and restore may be seen together. my $server = 0; if ($ARGV[0] eq "server") { - shift(@ARGV); - $server = 1; + shift(@ARGV); + $server = 1; } my $refresh = 0; if ($ARGV[0] eq "refresh") { - shift(@ARGV); - $refresh = 1; + shift(@ARGV); + $refresh = 1; } my $restore = 0; if ($ARGV[0] eq "restore") { - shift(@ARGV); - $restore = 1; - #print "Restore mode\n"; + shift(@ARGV); + $restore = 1; + #print "Restore mode\n"; } if ($server) { - runServer($restore); + runServer($restore); } elsif ($refresh) { - refreshConfig(); + refreshConfig(); } else { - runClient($restore); + runClient($restore); }