]> git.proxmox.com Git - pve-guest-common.git/blobdiff - PVE/GuestHelpers.pm
grammar fix: s/does not exists/does not exist/g
[pve-guest-common.git] / PVE / GuestHelpers.pm
index 35059e6393ce477bace2a9a4a91a57ef72e8fa12..07a62ce3a8ad960f61b3e05c27eec3c670e01b24 100644 (file)
@@ -7,6 +7,7 @@ use PVE::Tools;
 use PVE::Storage;
 
 use POSIX qw(strftime);
+use Scalar::Util qw(weaken);
 
 # We use a separate lock to block migration while a replication job
 # is running.
@@ -35,7 +36,7 @@ sub check_hookscript {
     die "'$volid' is not in the snippets directory\n"
        if $type ne 'snippets';
 
-    die "script '$volid' does not exists\n"
+    die "script '$volid' does not exist\n"
        if ! -f $path;
 
     die "script '$volid' is not executable\n"
@@ -87,8 +88,8 @@ sub print_snapshot_tree {
     };
 
     # recursion function for displaying the tree
-    my $snapshottree;
-    $snapshottree = sub {
+    my $snapshottree_weak;
+    $snapshottree_weak = sub {
        my ($prefix, $root, $snapshots) = @_;
        my $e = $snapshots->{$root};
 
@@ -106,14 +107,82 @@ sub print_snapshot_tree {
        if ($e->{children}) {
            $prefix = "    $prefix";
            foreach my $child (sort $snaptimesort @{$e->{children}}) {
-               $snapshottree->($prefix, $child, $snapshots);
+               $snapshottree_weak->($prefix, $child, $snapshots);
            }
        }
     };
+    my $snapshottree = $snapshottree_weak;
+    weaken($snapshottree_weak);
 
     foreach my $root (sort $snaptimesort @roots) {
        $snapshottree->('`->', $root, $snapshots);
     }
 }
 
+sub format_pending {
+    my ($data) = @_;
+    foreach my $item (sort { $a->{key} cmp $b->{key}} @$data) {
+       my $k = $item->{key};
+       next if $k eq 'digest';
+       my $v = $item->{value};
+       my $p = $item->{pending};
+       if ($k eq 'description') {
+           $v = PVE::Tools::encode_text($v) if defined($v);
+           $p = PVE::Tools::encode_text($p) if defined($p);
+       }
+       if (defined($v)) {
+           if ($item->{delete}) {
+               print "del $k: $v\n";
+           } elsif (defined($p)) {
+               print "cur $k: $v\n";
+               print "new $k: $p\n";
+           } else {
+               print "cur $k: $v\n";
+           }
+       } elsif (defined($p)) {
+           print "new $k: $p\n";
+       }
+    }
+}
+
+# returns the config as an array of hashes, each hash can have the following keys:
+# key (the config property name, non-optional)
+# value (the current value in effect - if any)
+# pending (a new, still pending, value - if any)
+# delete (when deletions are pending, this is set to either 2 (force) or 1 (graceful))
+sub config_with_pending_array {
+    my ($conf, $pending_delete_hash) = @_;
+
+    my $res = [];
+
+    foreach my $opt (keys %$conf) {
+       next if ref($conf->{$opt});
+       my $item = { key => $opt };
+       $item->{value} = $conf->{$opt} if defined($conf->{$opt});
+       $item->{pending} = $conf->{pending}->{$opt} if defined($conf->{pending}->{$opt});
+       $item->{delete} = ($pending_delete_hash->{$opt}->{force} ? 2 : 1) if exists $pending_delete_hash->{$opt};
+
+       push @$res, $item;
+    }
+
+    foreach my $opt (keys %{$conf->{pending}}) {
+       next if $opt eq 'delete';
+       next if ref($conf->{pending}->{$opt}); # just to be sure
+       next if defined($conf->{$opt});
+       my $item = { key => $opt };
+       $item->{pending} = $conf->{pending}->{$opt};
+
+       push @$res, $item;
+    }
+
+    while (my ($opt, $force) = each %$pending_delete_hash) {
+       next if $conf->{pending}->{$opt}; # just to be sure
+       next if $conf->{$opt};
+       my $item = { key => $opt, delete => ($force ? 2 : 1)};
+       push @$res, $item;
+    }
+
+    return $res;
+}
+
 1;