]> git.proxmox.com Git - pve-guest-common.git/blame - PVE/ReplicationConfig.pm
AbstractConfig.pm: remove code for replicate configuration
[pve-guest-common.git] / PVE / ReplicationConfig.pm
CommitLineData
87109d74
DM
1package PVE::ReplicationConfig;
2
3use strict;
4use warnings;
5use Data::Dumper;
6
7use PVE::Tools;
8use PVE::JSONSchema qw(get_standard_option);
9use PVE::INotify;
10use PVE::SectionConfig;
11use PVE::CalendarEvent;
12
13use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
14
15use base qw(PVE::SectionConfig);
16
17my $replication_cfg_filename = 'replication.cfg';
18
19cfs_register_file($replication_cfg_filename,
20 sub { __PACKAGE__->parse_config(@_); },
21 sub { __PACKAGE__->write_config(@_); });
22
23PVE::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
27});
28
29my $defaultData = {
30 propertyList => {
31 type => { description => "Section type." },
32 id => get_standard_option('pve-replication-id'),
33 disable => {
34 description => "Flag to disable/deactivate the entry.",
35 type => 'boolean',
36 optional => 1,
37 },
38 comment => {
39 description => "Description.",
40 type => 'string',
41 optional => 1,
42 maxLength => 4096,
43 },
44 guest => get_standard_option('pve-vmid', {
45 optional => 1,
46 completion => \&PVE::Cluster::complete_vmid }),
47 rate => {
48 description => "Rate limit in mbps (megabytes per second) as floating point number.",
49 type => 'number',
50 minimum => 1,
51 optional => 1,
52 },
53 schedule => {
54 description => "Storage replication schedule. The format is a subset of `systemd` calender events.",
55 type => 'string', format => 'pve-calendar-event',
56 maxLength => 128,
57 default => '*/15',
58 optional => 1,
59 },
60 },
61};
62
63sub private {
64 return $defaultData;
65}
66
67sub parse_section_header {
68 my ($class, $line) = @_;
69
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); };
74 $errmsg = $@ if $@;
75 my $config = {};
76 return ($type, $id, $errmsg, $config);
77 }
78 return undef;
79}
80
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.
84sub get_unique_target_id {
85 my ($class, $data) = @_;
86
87 die "please overwrite in subclass";
88}
89
90sub parse_config {
91 my ($class, $filename, $raw) = @_;
92
93 my $cfg = $class->SUPER::parse_config($filename, $raw);
94
95 my $target_hash = {};
96
97 foreach my $id (sort keys %{$cfg->{ids}}) {
98 my $data = $cfg->{ids}->{$id};
99
100 $data->{comment} = PVE::Tools::decode_text($data->{comment})
101 if defined($data->{comment});
102
103 my $plugin = $class->lookup($data->{type});
104 my $tid = $plugin->get_unique_target_id($data);
105 my $vmid = $data->{guest};
106
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};
111 }
112 $target_hash->{$vmid}->{$tid} = 1;
113 }
114
115 return $cfg;
116}
117
118sub write_config {
119 my ($class, $filename, $cfg) = @_;
120
121 my $target_hash = {};
122
123 foreach my $id (keys %{$cfg->{ids}}) {
124 my $data = $cfg->{ids}->{$id};
125
126 my $plugin = $class->lookup($data->{type});
127 my $tid = $plugin->get_unique_target_id($data);
128 my $vmid = $data->{guest};
129
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;
133
134 $data->{comment} = PVE::Tools::encode_text($data->{comment})
135 if defined($data->{comment});
136 }
137
138 $class->SUPER::write_config($filename, $cfg);
139}
140
141sub new {
142 my ($type) = @_;
143
144 my $class = ref($type) || $type;
145
146 my $cfg = cfs_read_file($replication_cfg_filename);
147
148 return bless $cfg, $class;
149}
150
151sub write {
152 my ($cfg) = @_;
153
154 cfs_write_file($replication_cfg_filename, $cfg);
155}
156
157sub lock {
158 my ($code, $errmsg) = @_;
159
160 cfs_lock_file($replication_cfg_filename, undef, $code);
161 my $err = $@;
162 if ($err) {
163 $errmsg ? die "$errmsg: $err" : die $err;
164 }
165}
166
167
168package PVE::ReplicationConfig::Cluster;
169
170use base qw(PVE::ReplicationConfig);
171
172sub type {
173 return 'local';
174}
175
176sub properties {
177 return {
178 target => {
179 description => "Target node.",
180 type => 'string', format => 'pve-node',
181 },
182 };
183}
184
185sub options {
186 return {
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 },
193 };
194}
195
196sub get_unique_target_id {
197 my ($class, $data) = @_;
198
199 return "local/$data->{target}";
200}
201
202PVE::ReplicationConfig::Cluster->register();
203PVE::ReplicationConfig->init();
204
2051;