package PVE::Job::Registry; use strict; use warnings; # The job (config) base class, normally you would use this in one of two variants: # # 1) base of directly in manager and handle everything there; great for stuff that isn't residing # outside of the manager, so that there is no cyclic dependency (forbidden!) required # # 2) use two (or even more) classes, one in the library (e.g., guest-common, access-control, ...) # basing off this module, providing the basic config implementation. Then one in pve-manager # (where every dependency is available) basing off the intermediate config one, that then holds # the implementation of the 'run` method and is used in the job manager use base qw(PVE::SectionConfig); my $defaultData = { propertyList => { type => { description => "Section type." }, # FIXME: remove below? this is the section ID, schema would only be checked if a plugin # declares this as explicit option, which isn't really required as its available anyway.. id => { description => "The ID of the job.", type => 'string', format => 'pve-configid', maxLength => 64, }, enabled => { description => "Determines if the job is enabled.", type => 'boolean', default => 1, optional => 1, }, schedule => { description => "Backup schedule. The format is a subset of `systemd` calendar events.", type => 'string', format => 'pve-calendar-event', maxLength => 128, }, comment => { optional => 1, type => 'string', description => "Description for the Job.", maxLength => 512, }, 'repeat-missed' => { optional => 1, type => 'boolean', description => "If true, the job will be run as soon as possible if it was missed". " while the scheduler was not running.", default => 0, }, }, }; sub private { return $defaultData; } sub parse_config { my ($class, $filename, $raw, $allow_unknown) = @_; my $cfg = $class->SUPER::parse_config($filename, $raw, $allow_unknown); for my $id (keys %{$cfg->{ids}}) { my $data = $cfg->{ids}->{$id}; my $type = $data->{type}; # FIXME: below id injection is gross, guard to avoid breaking plugins that don't declare id # as option; *iff* we want this it should be handled by section config directly. if ($defaultData->{options}->{$type} && exists $defaultData->{options}->{$type}->{id}) { $data->{id} = $id; } $data->{enabled} //= 1; $data->{comment} = PVE::Tools::decode_text($data->{comment}) if defined($data->{comment}); } return $cfg; } # call the plugin specific decode/encode code sub decode_value { my ($class, $type, $key, $value) = @_; my $plugin = __PACKAGE__->lookup($type); return $plugin->decode_value($type, $key, $value); } sub encode_value { my ($class, $type, $key, $value) = @_; my $plugin = __PACKAGE__->lookup($type); return $plugin->encode_value($type, $key, $value); } sub write_config { my ($class, $filename, $cfg, $allow_unknown) = @_; for my $job (values $cfg->{ids}->%*) { $job->{comment} = PVE::Tools::encode_text($job->{comment}) if defined($job->{comment}); } $class->SUPER::write_config($filename, $cfg, $allow_unknown); } sub run { my ($class, $cfg) = @_; die "not implemented"; # implement in subclass } 1;