]>
git.proxmox.com Git - pve-manager.git/blob - PVE/API2/ReplicationConfig.pm
1 package PVE
::API2
::ReplicationConfig
;
6 use PVE
::Tools
qw(extract_param);
7 use PVE
::Exception
qw(raise_perm_exc raise_param_exc);
8 use PVE
::JSONSchema
qw(get_standard_option);
9 use PVE
::RPCEnvironment
;
10 use PVE
::ReplicationConfig
;
15 use base
qw(PVE::RESTHandler);
17 __PACKAGE__-
>register_method ({
21 description
=> "List replication jobs.",
23 description
=> "Will only return replication jobs for which the calling user has"
24 . " VM.Audit permission on /vms/<vmid>.",
28 additionalProperties
=> 0,
37 links
=> [ { rel
=> 'child', href
=> "{id}" } ],
42 my $rpcenv = PVE
::RPCEnvironment
::get
();
43 my $authuser = $rpcenv->get_user();
45 my $cfg = PVE
::ReplicationConfig-
>new();
48 foreach my $id (sort keys %{$cfg->{ids
}}) {
49 my $d = $cfg->{ids
}->{$id};
50 my $vmid = $d->{guest
};
51 next if !$rpcenv->check($authuser, "/vms/$vmid", [ 'VM.Audit' ], 1);
59 __PACKAGE__-
>register_method ({
63 description
=> "Read replication job configuration.",
65 description
=> "Requires the VM.Audit permission on /vms/<vmid>.",
69 additionalProperties
=> 0,
71 id
=> get_standard_option
('pve-replication-id'),
74 returns
=> { type
=> 'object' },
78 my $rpcenv = PVE
::RPCEnvironment
::get
();
79 my $authuser = $rpcenv->get_user();
81 my $cfg = PVE
::ReplicationConfig-
>new();
83 my $data = $cfg->{ids
}->{$param->{id
}};
85 die "no such replication job '$param->{id}'\n" if !defined($data);
87 my $vmid = $data->{guest
};
89 raise_perm_exc
() if !$rpcenv->check($authuser, "/vms/$vmid", [ 'VM.Audit' ]);
91 $data->{id
} = $param->{id
};
93 $data->{digest
} = $cfg->{digest
};
98 __PACKAGE__-
>register_method ({
103 description
=> "Create a new replication job",
105 check
=> ['perm', '/storage', ['Datastore.Allocate']],
107 parameters
=> PVE
::ReplicationConfig-
>createSchema(),
108 returns
=> { type
=> 'null' },
112 my $type = extract_param
($param, 'type');
113 my $plugin = PVE
::ReplicationConfig-
>lookup($type);
114 my $id = extract_param
($param, 'id');
116 # extract guest ID from job ID
117 my ($guest) = PVE
::ReplicationConfig
::parse_replication_job_id
($id);
119 my $nodelist = PVE
::Cluster
::get_members
();
120 my $vmlist = PVE
::Cluster
::get_vmlist
();
122 my $guest_info = $vmlist->{ids
}->{$guest};
124 die "Guest '$guest' does not exist.\n"
125 if !defined($guest_info);
126 die "Target '$param->{target}' does not exist.\n"
127 if !defined($nodelist->{$param->{target
}});
129 my $source = $guest_info->{node
};
130 die "Source '$param->{source}' does not match current node of guest '$guest' ($source)\n"
131 if defined($param->{source
}) && $param->{source
} ne $source;
133 $param->{source
} //= $source;
135 die "Source and target must not be identical\n"
136 if $param->{target
} eq $source;
138 my $guest_class = $PVE::API2
::Replication
::lookup_guest_class-
>($guest_info->{type
});
139 my $guest_conf = $guest_class->load_config($guest, $source);
140 my $rep_volumes = $guest_class->get_replicatable_volumes(PVE
::Storage
::config
(), $guest, $guest_conf, 0, 0);
141 die "No replicatable volumes found\n" if !%$rep_volumes;
144 my $cfg = PVE
::ReplicationConfig-
>new();
146 die "replication job '$id' already exists\n"
147 if $cfg->{ids
}->{$id};
149 my $opts = $plugin->check_config($id, $param, 1, 1);
151 $opts->{guest
} = $guest;
153 $cfg->{ids
}->{$id} = $opts;
158 PVE
::ReplicationConfig
::lock($code);
164 __PACKAGE__-
>register_method ({
169 description
=> "Update replication job configuration.",
171 check
=> ['perm', '/storage', ['Datastore.Allocate']],
173 parameters
=> PVE
::ReplicationConfig-
>updateSchema(),
174 returns
=> { type
=> 'null' },
178 my $id = extract_param
($param, 'id');
179 my $digest = extract_param
($param, 'digest');
180 my $delete = extract_param
($param, 'delete');
183 my $cfg = PVE
::ReplicationConfig-
>new();
185 PVE
::SectionConfig
::assert_if_modified
($cfg, $digest);
187 my $data = $cfg->{ids
}->{$id};
188 die "no such job '$id'\n" if !$data;
190 my $plugin = PVE
::ReplicationConfig-
>lookup($data->{type
});
191 my $opts = $plugin->check_config($id, $param, 0, 1);
193 foreach my $k (keys %$opts) {
194 $data->{$k} = $opts->{$k};
198 my $options = $plugin->private()->{options
}->{$data->{type
}};
199 foreach my $k (PVE
::Tools
::split_list
($delete)) {
200 my $d = $options->{$k} ||
201 die "no such option '$k'\n";
202 die "unable to delete required option '$k'\n"
204 die "unable to delete fixed option '$k'\n"
213 PVE
::ReplicationConfig
::lock($code);
218 __PACKAGE__-
>register_method ({
223 description
=> "Mark replication job for removal.",
225 check
=> ['perm', '/storage', ['Datastore.Allocate']],
228 additionalProperties
=> 0,
230 id
=> get_standard_option
('pve-replication-id'),
232 description
=> "Keep replicated data at target (do not remove).",
238 description
=> "Will remove the jobconfig entry, but will not cleanup.",
245 returns
=> { type
=> 'null' },
249 my $rpcenv = PVE
::RPCEnvironment
::get
();
252 my $cfg = PVE
::ReplicationConfig-
>new();
254 my $id = $param->{id
};
255 if ($param->{force
}) {
256 raise_param_exc
({ 'keep' => "conflicts with parameter 'force'" }) if $param->{keep
};
257 delete $cfg->{ids
}->{$id};
259 my $jobcfg = $cfg->{ids
}->{$id};
260 die "no such job '$id'\n" if !$jobcfg;
262 if (!$param->{keep
} && $jobcfg->{type
} eq 'local') {
263 # remove local snapshots and remote volumes
264 $jobcfg->{remove_job
} = 'full';
266 # only remove local snapshots
267 $jobcfg->{remove_job
} = 'local';
270 warn "Replication job removal is a background task and will take some time.\n"
271 if $rpcenv->{type
} eq 'cli';
276 PVE
::ReplicationConfig
::lock($code);