]> git.proxmox.com Git - pve-guest-common.git/blobdiff - src/PVE/VZDump/Common.pm
vzdump: schema: make storage for fleecing semi-optional
[pve-guest-common.git] / src / PVE / VZDump / Common.pm
index bc38343550fe916bb9eadd97264cff82a7d658dd..153944431347245f443ef12e54cb78ab4466679e 100644 (file)
@@ -10,9 +10,12 @@ use PVE::Storage;
 use PVE::Cluster qw(cfs_register_file);
 use PVE::JSONSchema qw(get_standard_option);
 
-cfs_register_file('vzdump.cron',
-                 \&parse_vzdump_cron_config,
-                 \&write_vzdump_cron_config);
+# NOTE: this is the legacy config, nowadays jobs.cfg is used (handled in pve-manager)
+cfs_register_file(
+    'vzdump.cron',
+    \&parse_vzdump_cron_config,
+    \&write_vzdump_cron_config,
+);
 
 my $dowhash_to_dow = sub {
     my ($d, $num) = @_;
@@ -29,16 +32,22 @@ my $dowhash_to_dow = sub {
     return join ',', @da;
 };
 
-my $fixup_prune_backups_option = sub {
+our $PROPERTY_STRINGS = {
+    'fleecing' => 'backup-fleecing',
+    'performance' => 'backup-performance',
+    'prune-backups' => 'prune-backups',
+};
+
+my sub parse_property_strings {
     my ($opts) = @_;
 
-    return if !defined($opts->{'prune-backups'});
+    for my $opt (keys $PROPERTY_STRINGS->%*) {
+       next if !defined($opts->{$opt});
 
-    $opts->{'prune-backups'} = PVE::JSONSchema::parse_property_string(
-       'prune-backups',
-       $opts->{'prune-backups'}
-    );
-};
+       my $format = $PROPERTY_STRINGS->{$opt};
+       $opts->{$opt} = PVE::JSONSchema::parse_property_string($format, $opts->{$opt});
+    }
+}
 
 # parse crontab style day of week
 sub parse_dow {
@@ -71,6 +80,56 @@ sub parse_dow {
     return $res;
 };
 
+PVE::JSONSchema::register_format('backup-fleecing', {
+    enabled => {
+       description => "Enable backup fleecing. Cache backup data from blocks where new guest"
+           ." writes happen on specified storage instead of copying them directly to the backup"
+           ." target. This can help guest IO performance and even prevent hangs, at the cost of"
+           ." requiring more storage space.",
+       type => 'boolean',
+       default => 0,
+       optional => 1,
+       default_key => 1,
+    },
+    storage => get_standard_option('pve-storage-id', {
+       description => "Use this storage to storage fleecing images. For efficient space usage,"
+           ." it's best to use a local storage that supports discard and either thin provisioning"
+           ." or sparse files.",
+       optional => 1,
+    }),
+}, \&verify_backup_fleecing);
+
+sub verify_backup_fleecing {
+    my ($param, $noerr) = @_;
+
+    if (!$param->{storage} && $param->{enabled}) {
+       return if $noerr;
+       die "'storage' parameter is required when 'enabled' is set\n";
+    }
+
+    return $param;
+}
+
+PVE::JSONSchema::register_format('backup-performance', {
+    'max-workers' => {
+       description => "Applies to VMs. Allow up to this many IO workers at the same time.",
+       type => 'integer',
+       minimum => 1,
+       maximum => 256,
+       default => 16,
+       optional => 1,
+    },
+    'pbs-entries-max' => {
+       description => "Applies to container backups sent to PBS. Limits the number of entries"
+           ." allowed in memory at a given time to avoid unintended OOM situations. Increase it to"
+           ." enable backups of containers with a large amount of files.",
+       type => 'integer',
+       minimum => 1,
+       default => 1048576,
+       optional => 1,
+    },
+});
+
 my $confdesc = {
     vmid => {
        type => 'string', format => 'pve-vmid-list',
@@ -104,15 +163,15 @@ my $confdesc = {
     },
     pigz=> {
        type => "integer",
-       description => "Use pigz instead of gzip when N>0.".
-           " N=1 uses half of cores, N>1 uses N as thread count.",
+       description => "Use pigz instead of gzip when N>0. N=1 uses half of cores, N>1 uses N as"
+           ." thread count.",
        optional => 1,
        default => 0,
     },
     zstd => {
        type => "integer",
-       description => "Zstd threads. N=0 uses half of the available cores,".
-           " N>0 uses N as thread count.",
+       description => "Zstd threads. N=0 uses half of the available cores, if N is set to a value"
+           ." bigger than 0, N is used as thread count.",
        optional => 1,
        default => 1,
     },
@@ -135,26 +194,55 @@ my $confdesc = {
        optional => 1,
     },
     'exclude-path' => {
-       type => 'string', format => 'string-alist',
-       description => "Exclude certain files/directories (shell globs)." .
-           " Paths starting with '/' are anchored to the container's root, " .
-           " other paths match relative to each subdirectory.",
+       type => 'array',
+       description => "Exclude certain files/directories (shell globs). Paths starting with '/'"
+           ." are anchored to the container's root, other paths match relative to each"
+           ." subdirectory.",
        optional => 1,
+       items => {
+           type => 'string',
+       },
     },
     mailto => {
        type => 'string',
        format => 'email-or-username-list',
-       description => "Comma-separated list of email addresses or users that should" .
-           " receive email notifications.",
+       description => "Deprecated: Use notification targets/matchers instead. Comma-separated list"
+           ." of email addresses or users that should receive email notifications.",
        optional => 1,
     },
     mailnotification => {
        type => 'string',
-       description => "Specify when to send an email",
+       description => "Deprecated: use notification targets/matchers instead." .
+           " Specify when to send a notification mail",
        optional => 1,
        enum => [ 'always', 'failure' ],
        default => 'always',
     },
+    'notification-mode' => {
+       type => 'string',
+       description => "Determine which notification system to use. If set to 'legacy-sendmail',"
+           ." vzdump will consider the mailto/mailnotification parameters and send emails to the"
+           ." specified address(es) via the 'sendmail' command. If set to 'notification-system',"
+           ." a notification will be sent via PVE's notification system, and the mailto and"
+           ." mailnotification will be ignored. If set to 'auto' (default setting), an email will"
+           ." be sent if mailto is set, and the notification system will be used if not.",
+       optional => 1,
+       enum => ['auto', 'legacy-sendmail', 'notification-system'],
+       default => 'auto',
+    },
+    'notification-policy' => {
+       type => 'string',
+       description => "Deprecated: Do not use",
+       optional => 1,
+       enum => [ 'always', 'failure', 'never'],
+       default => 'always',
+    },
+    'notification-target' => {
+       type => 'string',
+       format => 'pve-configid',
+       description => "Deprecated: Do not use",
+       optional => 1,
+    },
     tmpdir => {
        type => 'string',
        description => "Store temporary files to specified directory.",
@@ -181,29 +269,36 @@ my $confdesc = {
        optional => 1,
        default => 0,
     },
-    # FIXME: Remove with PVE 7.0
-    size => {
-       type => 'integer',
-       description => "Unused, will be removed in a future release.",
-       optional => 1,
-       minimum => 500,
-       default => 1024,
-    },
     bwlimit => {
        type => 'integer',
-       description => "Limit I/O bandwidth (KBytes per second).",
+       description => "Limit I/O bandwidth (in KiB/s).",
        optional => 1,
        minimum => 0,
        default => 0,
     },
     ionice => {
        type => 'integer',
-       description => "Set CFQ ionice priority.",
+       description => "Set IO priority when using the BFQ scheduler. For snapshot and suspend"
+           ." mode backups of VMs, this only affects the compressor. A value of 8 means the idle"
+           ." priority is used, otherwise the best-effort priority is used with the specified"
+           ." value.",
        optional => 1,
        minimum => 0,
        maximum => 8,
        default => 7,
     },
+    performance => {
+       type => 'string',
+       description => "Other performance-related settings.",
+       format => 'backup-performance',
+       optional => 1,
+    },
+    fleecing => {
+       type => 'string',
+       description => "Options for backup fleecing (VM only).",
+       format => 'backup-fleecing',
+       optional => 1,
+    },
     lockwait => {
        type => 'integer',
        description => "Maximal time to wait for the global lock (minutes).",
@@ -218,21 +313,22 @@ my $confdesc = {
        minimum => 0,
        default => 10, # 10 minutes
     },
+    # FIXME remove with PVE 8.0 or PVE 9.0
     maxfiles => {
        type => 'integer',
-       description => "Maximal number of backup files per guest system.",
+       description => "Deprecated: use 'prune-backups' instead. " .
+           "Maximal number of backup files per guest system.",
        optional => 1,
        minimum => 1,
-       default => 1,
     },
     'prune-backups' => get_standard_option('prune-backups', {
        description => "Use these retention options instead of those from the storage configuration.",
        optional => 1,
+       default => "keep-all=1",
     }),
     remove => {
        type => 'boolean',
-       description => "Remove old backup files if there are more than " .
-           "'maxfiles' backup files or prune according to 'prune-backups'.",
+       description => "Prune older backups according to 'prune-backups'.",
        optional => 1,
        default => 1,
     },
@@ -240,7 +336,24 @@ my $confdesc = {
        type => 'string',
        description => 'Backup all known guest systems included in the specified pool.',
        optional => 1,
-    }
+    },
+    'notes-template' => {
+       type => 'string',
+       description => "Template string for generating notes for the backup(s). It can contain"
+           ." variables which will be replaced by their values. Currently supported are"
+           ." {{cluster}}, {{guestname}}, {{node}}, and {{vmid}}, but more might be added in the"
+           ." future. Needs to be a single line, newline and backslash need to be escaped as '\\n'"
+           ." and '\\\\' respectively.",
+       requires => 'storage',
+       maxLength => 1024,
+       optional => 1,
+    },
+    protected => {
+       type => 'boolean',
+       description => "If true, mark backup(s) as protected.",
+       requires => 'storage',
+       optional => 1,
+    },
 };
 
 sub get_confdesc {
@@ -301,7 +414,7 @@ sub parse_vzdump_cron_config {
                $opts->{starttime} = sprintf "%02d:%02d", $hour, $minute;
                $opts->{dow} = &$dowhash_to_dow($dowhash);
 
-               $fixup_prune_backups_option->($opts); # parse the property string
+               parse_property_strings($opts);
 
                push @$jobs, $opts;
            };
@@ -387,13 +500,13 @@ sub command_line {
        my $v = $param->{$p};
        my $pd = $confdesc->{$p} || die "no such vzdump option '$p'\n";
        if ($p eq 'exclude-path') {
-           foreach my $path (split(/\0/, $v || '')) {
+           foreach my $path (@$v) {
                $cmd .= " --$p " . PVE::Tools::shellquote($path);
            }
        } else {
            $v = join(",", PVE::Tools::split_list($v)) if $p eq 'mailto';
-           $v = PVE::JSONSchema::print_property_string($v, 'prune-backups')
-               if $p eq 'prune-backups';
+           $v = PVE::JSONSchema::print_property_string($v, $PROPERTY_STRINGS->{$p})
+               if $PROPERTY_STRINGS->{$p};
 
            $cmd .= " --$p " . PVE::Tools::shellquote($v) if defined($v) && $v ne '';
        }