]>
Commit | Line | Data |
---|---|---|
663510b8 WL |
1 | package PVE::CLI::pvesr; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
76c35814 | 5 | use POSIX qw(strftime); |
663510b8 | 6 | |
663510b8 WL |
7 | use PVE::JSONSchema qw(get_standard_option); |
8 | use PVE::INotify; | |
9 | use PVE::RPCEnvironment; | |
10 | use PVE::Tools qw(extract_param); | |
11 | use PVE::SafeSyslog; | |
12 | use PVE::CLIHandler; | |
76c35814 DM |
13 | |
14 | use PVE::API2::Storage::Replication; | |
663510b8 WL |
15 | |
16 | use base qw(PVE::CLIHandler); | |
17 | ||
18 | my $nodename = PVE::INotify::nodename(); | |
19 | ||
20 | sub setup_environment { | |
21 | PVE::RPCEnvironment->setup_default_cli_env(); | |
22 | } | |
23 | ||
24 | my $print_list = sub { | |
25 | my ($conf, $json) = @_; | |
26 | ||
27 | if (defined($json)) { | |
28 | print JSON::encode_json($conf); | |
29 | } else { | |
30 | printf("%-10s%-20s%-20s%-5s%-10s%-5s\n", | |
31 | "VMID", "DEST", "LAST SYNC","IVAL", "STATE", "FAIL"); | |
32 | ||
33 | foreach my $vmid (sort keys %$conf) { | |
34 | my $job = $conf->{$vmid}; | |
35 | my $timestr = strftime("%Y-%m-%d_%H:%M:%S", localtime($job->{lastsync})); | |
36 | ||
37 | printf("%-9s ", $vmid); | |
38 | printf("%-19s ", $job->{tnode}); | |
39 | printf("%-19s ", $timestr); | |
40 | printf("%-4s ", $job->{interval}); | |
41 | printf("%-9s ", $job->{state}); | |
42 | printf("%-9s\n", $job->{fail}); | |
43 | } | |
44 | } | |
45 | ||
46 | }; | |
47 | ||
48 | sub set_list { | |
49 | my ($list, $synctime, $vmid) = @_; | |
50 | ||
51 | if (defined($list->{$synctime})) { | |
52 | $list = set_list($list,$synctime+1, $vmid); | |
53 | } else { | |
54 | $list->{$synctime} = $vmid; | |
55 | } | |
56 | return $list; | |
57 | } | |
58 | ||
59 | my $get_replica_list = sub { | |
60 | ||
61 | my $jobs = PVE::ReplicationTools::read_state(); | |
62 | my $list = {}; | |
63 | ||
64 | foreach my $vmid (keys %$jobs) { | |
65 | my $job = $jobs->{$vmid}; | |
66 | my $lastsync = $job->{lastsync}; | |
67 | ||
68 | # interval in min | |
69 | my $interval = $job->{interval}; | |
70 | my $now = time(); | |
71 | my $fail = $job->{fail}; | |
72 | ||
73 | my $synctime = $lastsync + $interval * 60; | |
74 | ||
75 | if ($now >= $synctime && $job->{state} eq 'ok') { | |
76 | $list = set_list($list, $synctime, $vmid); | |
77 | } elsif ($job->{state} eq 'sync') { | |
78 | ||
79 | my $synctime += $interval * ($job->{fail}+1); | |
80 | $list = set_list($list, $synctime, $vmid) | |
81 | if ($now >= $synctime); | |
82 | ||
83 | } | |
84 | } | |
85 | ||
86 | return $list; | |
87 | }; | |
88 | ||
89 | my $replicate_vms = sub { | |
90 | my ($list) = @_; | |
91 | ||
92 | my @sorted_times = reverse sort keys %$list; | |
93 | ||
94 | foreach my $synctime (@sorted_times) { | |
95 | eval { | |
96 | PVE::ReplicationTools::sync_guest($list->{$synctime}); | |
97 | }; | |
98 | if (my $err = $@) { | |
99 | syslog ('err', $err ); | |
100 | } | |
101 | } | |
102 | }; | |
103 | ||
104 | __PACKAGE__->register_method ({ | |
105 | name => 'run', | |
106 | path => 'run', | |
107 | method => 'POST', | |
108 | description => "This method will run by the systemd-timer and sync all jobs", | |
109 | permissions => { | |
110 | description => { | |
111 | check => ['perm', '/', [ 'Sys.Console' ]], | |
112 | }, | |
113 | }, | |
114 | protected => 1, | |
115 | parameters => { | |
116 | additionalProperties => 0, | |
117 | properties => { | |
118 | }, | |
119 | }, | |
120 | returns => { type => 'null' }, | |
121 | code => sub { | |
122 | ||
123 | my $list = &$get_replica_list(); | |
124 | &$replicate_vms($list); | |
125 | ||
126 | return undef; | |
127 | }}); | |
128 | ||
129 | __PACKAGE__->register_method ({ | |
130 | name => 'destroyjob', | |
131 | path => 'destroyjob', | |
132 | method => 'DELETE', | |
133 | description => "Destroy an async replication job", | |
134 | permissions => { | |
135 | description => { | |
136 | check => ['perm', '/storage', ['Datastore.Allocate']], | |
137 | }, | |
138 | }, | |
139 | protected => 1, | |
140 | parameters => { | |
141 | additionalProperties => 0, | |
142 | properties => { | |
143 | vmid => { | |
144 | type => 'string', format => 'pve-vmid', | |
145 | description => "The VMID of the guest.", | |
146 | completion => \&PVE::Cluster::complete_local_vmid, | |
147 | }, | |
148 | }, | |
149 | }, | |
150 | returns => { type => 'null' }, | |
151 | code => sub { | |
152 | my ($param) = @_; | |
153 | ||
154 | my $vmid = extract_param($param, 'vmid'); | |
155 | ||
156 | PVE::ReplicationTools::destroy_replica($vmid); | |
157 | ||
158 | }}); | |
159 | ||
160 | __PACKAGE__->register_method ({ | |
161 | name => 'list', | |
162 | path => 'list', | |
163 | method => 'GET', | |
164 | description => "List of all replication jobs.", | |
165 | permissions => { | |
166 | user => 'all' | |
167 | }, | |
168 | protected => 1, | |
169 | parameters => { | |
170 | additionalProperties => 0, | |
171 | properties => { | |
172 | vmid => { | |
173 | type => 'string', format => 'pve-vmid', | |
174 | description => "The VMID of the guest.", | |
175 | completion => \&PVE::Cluster::complete_local_vmid, | |
176 | }, | |
177 | }, | |
178 | }, | |
179 | protected => 1, | |
180 | proxyto => 'node', | |
181 | parameters => { | |
182 | additionalProperties => 0, | |
183 | properties => { | |
184 | node => get_standard_option('pve-node'), | |
185 | nodes => get_standard_option('pve-node-list' , | |
186 | {description => "Notes where the jobs is located.", | |
187 | optional => 1}), | |
188 | json => { | |
189 | optional => 1, | |
190 | type => 'boolean', | |
191 | description => "Output in JSON format.", | |
192 | }, | |
193 | }, | |
194 | }, | |
195 | returns => { type => 'string' }, | |
196 | code => sub { | |
197 | my ($param) = @_; | |
198 | ||
199 | if ($param->{nodes}) { | |
200 | foreach my $node (PVE::Tools::split_list($param->{nodes})) { | |
201 | die "Node: $node does not exists.\n" if | |
202 | !PVE::Cluster::check_node_exists($node); | |
203 | } | |
204 | } | |
205 | ||
206 | my $nodes = $param->{nodes} ? | |
207 | $param->{nodes} : $param->{node}; | |
208 | ||
209 | my $list = PVE::ReplicationTools::get_all_jobs($nodes); | |
210 | ||
211 | &$print_list($list, $param->{json}); | |
212 | }}); | |
213 | ||
214 | ||
215 | our $cmddef = { | |
216 | list => [ __PACKAGE__ , 'list' , [], {node => $nodename}], | |
217 | run => [ __PACKAGE__ , 'run'], | |
218 | destroyjob => [ __PACKAGE__ , 'destroyjob', ['vmid']], | |
219 | }; | |
220 | ||
221 | 1; |