]>
git.proxmox.com Git - pve-manager.git/blob - PVE/API2/Replication.pm
d25b744a968c152bd7bab773c4c5ec0c2fe2b614
1 package PVE
::API2
::Replication
;
6 use PVE
::JSONSchema
qw(get_standard_option);
7 use PVE
::RPCEnvironment
;
9 use PVE
::ReplicationConfig
;
10 use PVE
::ReplicationState
;
19 use base
qw(PVE::RESTHandler);
21 our $pvesr_lock_path = "/var/lock/pvesr.lck";
23 our $lookup_guest_class = sub {
26 if ($vmtype eq 'qemu') {
27 return 'PVE::QemuConfig';
28 } elsif ($vmtype eq 'lxc') {
29 return 'PVE::LXC::Config';
31 die "unknown guest type '$vmtype' - internal error";
35 # passing $now is useful for regression testing
37 my ($jobid, $now, $logfunc) = @_;
39 my $local_node = PVE
::INotify
::nodename
();
44 my $cfg = PVE
::ReplicationConfig-
>new();
46 my $jobcfg = $cfg->{ids
}->{$jobid};
47 die "no such job '$jobid'\n" if !$jobcfg;
49 die "internal error - not implemented" if $jobcfg->{type
} ne 'local';
51 die "job '$jobid' is disabled\n" if $jobcfg->{disable
};
53 my $vms = PVE
::Cluster
::get_vmlist
();
54 my $vmid = $jobcfg->{guest
};
56 die "no such guest '$vmid'\n" if !$vms->{ids
}->{$vmid};
58 die "guest '$vmid' is not on local node\n"
59 if $vms->{ids
}->{$vmid}->{node
} ne $local_node;
61 die "unable to sync to local node\n" if $jobcfg->{target
} eq $local_node;
63 $jobcfg->{id
} = $jobid;
65 my $vmtype = $vms->{ids
}->{$vmid}->{type
};
67 my $guest_class = $lookup_guest_class->($vmtype);
68 PVE
::Replication
::run_replication
($guest_class, $jobcfg, $now, $now, $logfunc);
71 my $res = PVE
::Tools
::lock_file
($pvesr_lock_path, 60, $code);
75 # passing $now and $verbose is useful for regression testing
77 my ($now, $logfunc, $verbose) = @_;
79 my $iteration = $now // time();
82 my $start_time = $now // time();
84 PVE
::ReplicationState
::purge_old_states
();
86 while (my $jobcfg = PVE
::ReplicationState
::get_next_job
($iteration, $start_time)) {
87 my $guest_class = $lookup_guest_class->($jobcfg->{vmtype
});
88 PVE
::Replication
::run_replication
($guest_class, $jobcfg, $iteration, $start_time, $logfunc, 1, $verbose);
89 $start_time = $now // time();
93 my $res = PVE
::Tools
::lock_file
($pvesr_lock_path, 60, $code);
97 my $extract_job_status = sub {
98 my ($jobcfg, $jobid) = @_;
100 # Note: we modify $jobcfg
101 my $state = delete $jobcfg->{state};
104 $data->{id
} = $jobid;
106 foreach my $k (qw(last_sync last_try fail_count error duration)) {
107 $data->{$k} = $state->{$k} if defined($state->{$k});
110 if ($state->{pid
} && $state->{ptime
}) {
111 if (PVE
::ProcFSTools
::check_process_running
($state->{pid
}, $state->{ptime
})) {
112 $data->{pid
} = $state->{pid
};
119 __PACKAGE__-
>register_method ({
123 description
=> "List status of all replication jobs on this node.",
125 description
=> "Requires the VM.Audit permission on /vms/<vmid>.",
131 additionalProperties
=> 0,
133 node
=> get_standard_option
('pve-node'),
134 guest
=> get_standard_option
('pve-vmid', {
136 description
=> "Only list replication jobs for this guest.",
145 id
=> { type
=> 'string' },
148 links
=> [ { rel
=> 'child', href
=> "{id}" } ],
153 my $rpcenv = PVE
::RPCEnvironment
::get
();
154 my $authuser = $rpcenv->get_user();
156 my $jobs = PVE
::ReplicationState
::job_status
();
159 foreach my $id (sort keys %$jobs) {
160 my $data = $extract_job_status->($jobs->{$id}, $id);
161 my $guest = $data->{guest
};
162 next if defined($param->{guest
}) && $guest != $param->{guest
};
163 next if !$rpcenv->check($authuser, "/vms/$guest", [ 'VM.Audit' ]);
170 __PACKAGE__-
>register_method ({
174 permissions
=> { user
=> 'all' },
175 description
=> "Directory index.",
177 additionalProperties
=> 0,
179 id
=> get_standard_option
('pve-replication-id'),
180 node
=> get_standard_option
('pve-node'),
189 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
195 { name
=> 'schedule_now' },
197 { name
=> 'status' },
202 __PACKAGE__-
>register_method ({
203 name
=> 'job_status',
204 path
=> '{id}/status',
206 description
=> "Get replication job status.",
208 description
=> "Requires the VM.Audit permission on /vms/<vmid>.",
214 additionalProperties
=> 0,
216 id
=> get_standard_option
('pve-replication-id'),
217 node
=> get_standard_option
('pve-node'),
227 my $rpcenv = PVE
::RPCEnvironment
::get
();
228 my $authuser = $rpcenv->get_user();
230 my $jobs = PVE
::ReplicationState
::job_status
();
231 my $jobid = $param->{id
};
232 my $jobcfg = $jobs->{$jobid};
234 die "no such replication job '$jobid'\n" if !defined($jobcfg);
236 my $data = $extract_job_status->($jobcfg, $jobid);
237 my $guest = $data->{guest
};
239 raise_perm_exc
() if !$rpcenv->check($authuser, "/vms/$guest", [ 'VM.Audit' ]);
244 __PACKAGE__-
>register_method({
245 name
=> 'read_job_log',
249 description
=> "Requires the VM.Audit permission on /vms/<vmid>, or 'Sys.Audit' on '/nodes/<node>'",
253 description
=> "Read replication job log.",
256 additionalProperties
=> 0,
258 id
=> get_standard_option
('pve-replication-id'),
259 node
=> get_standard_option
('pve-node'),
278 description
=> "Line number",
282 description
=> "Line text",
291 my $rpcenv = PVE
::RPCEnvironment
::get
();
292 my $authuser = $rpcenv->get_user();
294 my $jobid = $param->{id
};
295 my $filename = PVE
::ReplicationState
::job_logfile_name
($jobid);
297 my $cfg = PVE
::ReplicationConfig-
>new();
298 my $data = $cfg->{ids
}->{$jobid};
300 die "no such replication job '$jobid'\n" if !defined($data);
302 my $node = $param->{node
};
304 my $vmid = $data->{guest
};
305 raise_perm_exc
() if (!($rpcenv->check($authuser, "/vms/$vmid", [ 'VM.Audit' ]) ||
306 $rpcenv->check($authuser, "/nodes/$node", [ 'Sys.Audit' ])));
308 my ($count, $lines) = PVE
::Tools
::dump_logfile
($filename, $param->{start
}, $param->{limit
});
310 $rpcenv->set_result_attrib('total', $count);
315 __PACKAGE__-
>register_method ({
316 name
=> 'schedule_now',
317 path
=> '{id}/schedule_now',
319 description
=> "Schedule replication job to start as soon as possible.",
323 check
=> ['perm', '/storage', ['Datastore.Allocate']],
326 additionalProperties
=> 0,
328 id
=> get_standard_option
('pve-replication-id'),
329 node
=> get_standard_option
('pve-node'),
338 my $jobid = $param->{id
};
340 my $cfg = PVE
::ReplicationConfig-
>new();
341 my $jobcfg = $cfg->{ids
}->{$jobid};
343 die "no such replication job '$jobid'\n" if !defined($jobcfg);
345 PVE
::ReplicationState
::schedule_job_now
($jobcfg);