]> git.proxmox.com Git - pve-manager.git/blame - PVE/API2/ReplicationConfig.pm
bump version to 5.0-16
[pve-manager.git] / PVE / API2 / ReplicationConfig.pm
CommitLineData
892821fd
DM
1package PVE::API2::ReplicationConfig;
2
3use warnings;
4use strict;
5
6use PVE::Tools qw(extract_param);
f9d38c54 7use PVE::Exception qw(raise_perm_exc raise_param_exc);
892821fd
DM
8use PVE::JSONSchema qw(get_standard_option);
9use PVE::RPCEnvironment;
10use PVE::ReplicationConfig;
4542a42a 11use PVE::Cluster;
892821fd
DM
12
13use PVE::RESTHandler;
14
15use base qw(PVE::RESTHandler);
16
17__PACKAGE__->register_method ({
18 name => 'index',
19 path => '',
20 method => 'GET',
21 description => "List replication jobs.",
22 permissions => {
23 description => "Requires the VM.Audit permission on /vms/<vmid>.",
24 user => 'all',
25 },
26 parameters => {
27 additionalProperties => 0,
28 properties => {},
29 },
30 returns => {
31 type => 'array',
32 items => {
33 type => "object",
34 properties => {},
35 },
4b48563a 36 links => [ { rel => 'child', href => "{id}" } ],
892821fd
DM
37 },
38 code => sub {
39 my ($param) = @_;
40
41 my $rpcenv = PVE::RPCEnvironment::get();
42 my $authuser = $rpcenv->get_user();
43
44 my $cfg = PVE::ReplicationConfig->new();
45
46 my $res = [];
47 foreach my $id (sort keys %{$cfg->{ids}}) {
48 my $d = $cfg->{ids}->{$id};
49 my $vmid = $d->{guest};
50 next if !$rpcenv->check($authuser, "/vms/$vmid", [ 'VM.Audit' ]);
51 $d->{id} = $id;
52 push @$res, $d;
53 }
54
55 return $res;
56 }});
57
58__PACKAGE__->register_method ({
59 name => 'read',
60 path => '{id}',
61 method => 'GET',
62 description => "Read replication job configuration.",
63 permissions => {
64 description => "Requires the VM.Audit permission on /vms/<vmid>.",
65 user => 'all',
66 },
67 parameters => {
68 additionalProperties => 0,
69 properties => {
70 id => get_standard_option('pve-replication-id'),
71 },
72 },
73 returns => { type => 'object' },
74 code => sub {
75 my ($param) = @_;
76
77 my $rpcenv = PVE::RPCEnvironment::get();
78 my $authuser = $rpcenv->get_user();
79
80 my $cfg = PVE::ReplicationConfig->new();
81
82 my $data = $cfg->{ids}->{$param->{id}};
83
84 die "no such replication job '$param->{id}'\n" if !defined($data);
85
86 my $vmid = $data->{guest};
87
88 raise_perm_exc() if !$rpcenv->check($authuser, "/vms/$vmid", [ 'VM.Audit' ]);
89
90 $data->{id} = $param->{id};
91
a4dc8611
DC
92 $data->{digest} = $cfg->{digest};
93
892821fd
DM
94 return $data;
95 }});
96
97__PACKAGE__->register_method ({
98 name => 'create',
99 path => '',
100 protected => 1,
101 method => 'POST',
102 description => "Create a new replication job",
103 permissions => {
104 check => ['perm', '/storage', ['Datastore.Allocate']],
105 },
106 parameters => PVE::ReplicationConfig->createSchema(),
107 returns => { type => 'null' },
108 code => sub {
109 my ($param) = @_;
110
111 my $type = extract_param($param, 'type');
112 my $plugin = PVE::ReplicationConfig->lookup($type);
113 my $id = extract_param($param, 'id');
114
a9da300d
DM
115 # extract guest ID from job ID
116 my ($guest) = PVE::ReplicationConfig::parse_replication_job_id($id);
117
4542a42a
DM
118 my $nodelist = PVE::Cluster::get_members();
119 my $vmlist = PVE::Cluster::get_vmlist();
120
121 die "Guest '$guest' does not exists.\n"
122 if !defined($vmlist->{ids}->{$guest});
123 die "Target '$param->{target}' does not exists.\n"
124 if defined($param->{target}) && !defined($nodelist->{$param->{target}});
125
892821fd
DM
126 my $code = sub {
127 my $cfg = PVE::ReplicationConfig->new();
128
892821fd
DM
129 die "replication job '$id' already exists\n"
130 if $cfg->{ids}->{$id};
131
132 my $opts = $plugin->check_config($id, $param, 1, 1);
133
a9da300d
DM
134 $opts->{guest} = $guest;
135
892821fd
DM
136 $cfg->{ids}->{$id} = $opts;
137
138 $cfg->write();
139 };
140
141 PVE::ReplicationConfig::lock($code);
142
143 return undef;
144 }});
145
146
147__PACKAGE__->register_method ({
148 name => 'update',
149 protected => 1,
150 path => '{id}',
151 method => 'PUT',
152 description => "Update replication job configuration.",
153 permissions => {
154 check => ['perm', '/storage', ['Datastore.Allocate']],
155 },
156 parameters => PVE::ReplicationConfig->updateSchema(),
157 returns => { type => 'null' },
158 code => sub {
159 my ($param) = @_;
160
161 my $id = extract_param($param, 'id');
a4dc8611 162 my $digest = extract_param($param, 'digest');
dc9bc768 163 my $delete = extract_param($param, 'delete');
892821fd
DM
164
165 my $code = sub {
166 my $cfg = PVE::ReplicationConfig->new();
167
a4dc8611
DC
168 PVE::SectionConfig::assert_if_modified($cfg, $digest);
169
892821fd
DM
170 my $data = $cfg->{ids}->{$id};
171 die "no such job '$id'\n" if !$data;
172
173 my $plugin = PVE::ReplicationConfig->lookup($data->{type});
174 my $opts = $plugin->check_config($id, $param, 0, 1);
175
176 foreach my $k (%$opts) {
177 $data->{$k} = $opts->{$k};
178 }
179
dc9bc768
DC
180 if ($delete) {
181 my $options = $plugin->private()->{options}->{$data->{type}};
182 foreach my $k (PVE::Tools::split_list($delete)) {
183 my $d = $options->{$k} ||
184 die "no such option '$k'\n";
185 die "unable to delete required option '$k'\n"
186 if !$d->{optional};
187 die "unable to delete fixed option '$k'\n"
188 if $d->{fixed};
189 delete $data->{$k};
190 }
191 }
192
892821fd
DM
193 $cfg->write();
194 };
195
196 PVE::ReplicationConfig::lock($code);
197
198 return undef;
199 }});
200
201__PACKAGE__->register_method ({
202 name => 'delete',
203 protected => 1,
204 path => '{id}',
205 method => 'DELETE',
f9d38c54 206 description => "Mark replication job for removal.",
892821fd
DM
207 permissions => {
208 check => ['perm', '/storage', ['Datastore.Allocate']],
209 },
210 parameters => {
211 additionalProperties => 0,
212 properties => {
213 id => get_standard_option('pve-replication-id'),
214 keep => {
215 description => "Keep replicated data at target (do not remove).",
216 type => 'boolean',
217 optional => 1,
218 default => 0,
219 },
948136a4
WL
220 force => {
221 description => "Will remove the jobconfig entry, but will not cleanup.",
222 type => 'boolean',
223 optional => 1,
224 default => 0,
225 },
892821fd
DM
226 }
227 },
228 returns => { type => 'null' },
229 code => sub {
230 my ($param) = @_;
231
bc1ec7bc
DM
232 my $rpcenv = PVE::RPCEnvironment::get();
233
892821fd
DM
234 my $code = sub {
235 my $cfg = PVE::ReplicationConfig->new();
236
f9d38c54 237 my $id = $param->{id};
948136a4 238 if ($param->{force}) {
9a427c6c 239 raise_param_exc({ 'keep' => "conflicts with parameter 'force'" }) if $param->{keep};
948136a4 240 delete $cfg->{ids}->{$id};
f9d38c54 241 } else {
948136a4
WL
242 my $jobcfg = $cfg->{ids}->{$id};
243 die "no such job '$id'\n" if !$jobcfg;
244
245 if (!$param->{keep} && $jobcfg->{type} eq 'local') {
246 # remove local snapshots and remote volumes
247 $jobcfg->{remove_job} = 'full';
248 } else {
249 # only remove local snapshots
250 $jobcfg->{remove_job} = 'local';
251 }
252
253 warn "Replication job removal is a background task and will take some time.\n"
254 if $rpcenv->{type} eq 'cli';
892821fd 255 }
892821fd
DM
256 $cfg->write();
257 };
258
259 PVE::ReplicationConfig::lock($code);
260
261 return undef;
262 }});
f9d38c54 263
892821fd 2641;