]> git.proxmox.com Git - pve-guest-common.git/blobdiff - PVE/GuestHelpers.pm
followup: rename to print_snapshot_tree, add comment and rename $res param
[pve-guest-common.git] / PVE / GuestHelpers.pm
index 892b6db187f6c36534bc9c69f37755f38554da72..35059e6393ce477bace2a9a4a91a57ef72e8fa12 100644 (file)
@@ -6,6 +6,8 @@ use warnings;
 use PVE::Tools;
 use PVE::Storage;
 
+use POSIX qw(strftime);
+
 # We use a separate lock to block migration while a replication job
 # is running.
 
@@ -46,28 +48,72 @@ sub exec_hookscript {
     my ($conf, $vmid, $phase, $stop_on_error) = @_;
 
     return if !$conf->{hookscript};
-    my $hookscript = eval { check_hookscript($conf->{hookscript}) };
-    if (my $err = $@) {
-       if ($stop_on_error) {
-           die $err;
-       } else {
-           warn $err;
-           return;
-       }
-    }
 
     eval {
+       my $hookscript = check_hookscript($conf->{hookscript});
+       die $@ if $@;
+
        PVE::Tools::run_command([$hookscript, $vmid, $phase]);
     };
-
     if (my $err = $@) {
        my $errmsg = "hookscript error for $vmid on $phase: $err\n";
-       if ($stop_on_error) {
-           die $errmsg;
+       die $errmsg if ($stop_on_error);
+       warn $errmsg;
+    }
+}
+
+# takes a snapshot list (e.g., qm/pct snapshot_list API call result) and
+# prints it out in a nice tree sorted by age. Can cope with multiple roots
+sub print_snapshot_tree {
+    my ($snapshot_list) = @_;
+
+    my $snapshots = { map { $_->{name} => $_ } @$snapshot_list };
+
+    my @roots;
+    foreach my $e (@$snapshot_list) {
+       my $parent;
+       if (($parent = $e->{parent}) && defined $snapshots->{$parent}) {
+           push @{$snapshots->{$parent}->{children}}, $e->{name};
        } else {
-           warn $errmsg;
+           push @roots, $e->{name};
        }
     }
+
+    # sort the elements by snaptime - with "current" (no snaptime) highest
+    my $snaptimesort = sub {
+       return +1 if !defined $snapshots->{$a}->{snaptime};
+       return -1 if !defined $snapshots->{$b}->{snaptime};
+       return $snapshots->{$a}->{snaptime} <=> $snapshots->{$b}->{snaptime};
+    };
+
+    # recursion function for displaying the tree
+    my $snapshottree;
+    $snapshottree = sub {
+       my ($prefix, $root, $snapshots) = @_;
+       my $e = $snapshots->{$root};
+
+       my $description = $e->{description} || 'no-description';
+       ($description) = $description =~ m/(.*)$/m;
+
+       my $timestring = "";
+       if (defined $e->{snaptime}) {
+           $timestring = strftime("%F %H:%M:%S", localtime($e->{snaptime}));
+       }
+
+       my $len = 30 - length($prefix); # for aligning the description
+       printf("%s %-${len}s %-23s %s\n", $prefix, $root, $timestring, $description);
+
+       if ($e->{children}) {
+           $prefix = "    $prefix";
+           foreach my $child (sort $snaptimesort @{$e->{children}}) {
+               $snapshottree->($prefix, $child, $snapshots);
+           }
+       }
+    };
+
+    foreach my $root (sort $snaptimesort @roots) {
+       $snapshottree->('`->', $root, $snapshots);
+    }
 }
 
 1;