]>
git.proxmox.com Git - pve-guest-common.git/blob - PVE/ReplicationConfig.pm
1 package PVE
::ReplicationConfig
;
8 use PVE
::JSONSchema
qw(get_standard_option);
10 use PVE
::SectionConfig
;
11 use PVE
::CalendarEvent
;
13 use PVE
::Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
15 use base
qw(PVE::SectionConfig);
17 my $replication_cfg_filename = 'replication.cfg';
19 cfs_register_file
($replication_cfg_filename,
20 sub { __PACKAGE__-
>parse_config(@_); },
21 sub { __PACKAGE__-
>write_config(@_); });
23 PVE
::JSONSchema
::register_standard_option
('pve-replication-id', {
24 description
=> "Replication Job ID.",
25 type
=> 'string', format
=> 'pve-configid',
26 maxLength
=> 32, # keep short to reduce snapshot name length
31 type
=> { description
=> "Section type." },
32 id
=> get_standard_option
('pve-replication-id'),
34 description
=> "Flag to disable/deactivate the entry.",
39 description
=> "Description.",
44 guest
=> get_standard_option
('pve-vmid', {
46 completion
=> \
&PVE
::Cluster
::complete_vmid
}),
48 description
=> "Rate limit in mbps (megabytes per second) as floating point number.",
54 description
=> "Storage replication schedule. The format is a subset of `systemd` calender events.",
55 type
=> 'string', format
=> 'pve-calendar-event',
67 sub parse_section_header
{
68 my ($class, $line) = @_;
70 if ($line =~ m/^(\S+):\s*(\S+)\s*$/) {
71 my ($type, $id) = (lc($1), $2);
72 my $errmsg = undef; # set if you want to skip whole section
73 eval { PVE
::JSONSchema
::pve_verify_configid
($id); };
76 return ($type, $id, $errmsg, $config);
81 # Note: We want only one replication job per target to
82 # avoid confusion. This method should return a string
83 # which uniquely identifies the target.
84 sub get_unique_target_id
{
85 my ($class, $data) = @_;
87 die "please overwrite in subclass";
91 my ($class, $filename, $raw) = @_;
93 my $cfg = $class->SUPER::parse_config
($filename, $raw);
97 foreach my $id (sort keys %{$cfg->{ids
}}) {
98 my $data = $cfg->{ids
}->{$id};
100 $data->{comment
} = PVE
::Tools
::decode_text
($data->{comment
})
101 if defined($data->{comment
});
103 my $plugin = $class->lookup($data->{type
});
104 my $tid = $plugin->get_unique_target_id($data);
105 my $vmid = $data->{guest
};
107 # should not happen, but we want to be sure
108 if (defined($target_hash->{$vmid}->{$tid})) {
109 warn "delete job $id: replication job for guest '$vmid' to target '$tid' already exists\n";
110 delete $cfg->{ids
}->{$id};
112 $target_hash->{$vmid}->{$tid} = 1;
119 my ($class, $filename, $cfg) = @_;
121 my $target_hash = {};
123 foreach my $id (keys %{$cfg->{ids
}}) {
124 my $data = $cfg->{ids
}->{$id};
126 my $plugin = $class->lookup($data->{type
});
127 my $tid = $plugin->get_unique_target_id($data);
128 my $vmid = $data->{guest
};
130 die "replication job for guest '$vmid' to target '$tid' already exists\n"
131 if defined($target_hash->{$vmid}->{$tid});
132 $target_hash->{$vmid}->{$tid} = 1;
134 $data->{comment
} = PVE
::Tools
::encode_text
($data->{comment
})
135 if defined($data->{comment
});
138 $class->SUPER::write_config
($filename, $cfg);
144 my $class = ref($type) || $type;
146 my $cfg = cfs_read_file
($replication_cfg_filename);
148 return bless $cfg, $class;
154 cfs_write_file
($replication_cfg_filename, $cfg);
158 my ($code, $errmsg) = @_;
160 cfs_lock_file
($replication_cfg_filename, undef, $code);
163 $errmsg ?
die "$errmsg: $err" : die $err;
168 package PVE
::ReplicationConfig
::Cluster
;
170 use base
qw(PVE::ReplicationConfig);
179 description
=> "Target node.",
180 type
=> 'string', format
=> 'pve-node',
187 guest
=> { fixed
=> 1, optional
=> 0 },
188 target
=> { fixed
=> 1, optional
=> 0 },
189 disable
=> { optional
=> 1 },
190 comment
=> { optional
=> 1 },
191 rate
=> { optional
=> 1 },
192 schedule
=> { optional
=> 1 },
196 sub get_unique_target_id
{
197 my ($class, $data) = @_;
199 return "local/$data->{target}";
202 PVE
::ReplicationConfig
::Cluster-
>register();
203 PVE
::ReplicationConfig-
>init();