]>
git.proxmox.com Git - pve-manager.git/blob - bin/test/ReplicationTestEnv.pm
cdf81f05ebc23b8956f2b27e6aabe6d1403b924f
1 package ReplicationTestEnv
;
9 use lib
('.', '../..');
16 use PVE
::ReplicationConfig
;
17 use PVE
::ReplicationState
;
24 our $mocked_nodename = 'node1';
26 our $mocked_replication_jobs = {};
28 my $pve_replicationconfig = Test
::MockModule-
>new('PVE::ReplicationConfig');
30 our $mocked_vm_configs = {};
32 our $mocked_ct_configs = {};
34 my $mocked_vmlist = sub {
37 foreach my $id (keys %$mocked_ct_configs) {
38 my $d = $mocked_ct_configs->{$id};
39 $res->{$id} = { 'type' => 'lxc', 'node' => $d->{node
}, 'version' => 1 };
41 foreach my $id (keys %$mocked_vm_configs) {
42 my $d = $mocked_vm_configs->{$id};
43 $res->{$id} = { 'type' => 'qemu', 'node' => $d->{node
}, 'version' => 1 };
46 return { 'ids' => $res };
49 my $mocked_get_ssh_info = sub {
50 my ($node, $network_cidr) = @_;
52 return { node
=> $node };
55 my $mocked_ssh_info_to_command = sub {
56 my ($info, @extra_options) = @_;
58 return ['fake_ssh', $info->{name
}, @extra_options];
61 my $statefile = ".mocked_repl_state";
64 $PVE::ReplicationState
::state_path
= $statefile;
65 $PVE::ReplicationState
::state_lock
= ".mocked_repl_state_lock";
66 $PVE::Replication
::pvesr_lock_path
= ".mocked_pvesr_lock";
67 $PVE::GuestHelpers
::lockdir
= ".mocked_pve-manager_lock";
69 if (!mkdir($PVE::GuestHelpers
::lockdir
) && !$!{EEXIST
}) {
70 # If we cannot create the guest helper lockdir we'll loop endlessly, so die
72 die "mkdir($PVE::GuestHelpers::lockdir): $!\n";
75 my $pve_cluster_module = Test
::MockModule-
>new('PVE::Cluster');
77 my $pve_inotify_module = Test
::MockModule-
>new('PVE::INotify');
79 my $mocked_qemu_load_conf = sub {
80 my ($class, $vmid, $node) = @_;
82 $node = $mocked_nodename if !$node;
84 my $conf = $mocked_vm_configs->{$vmid};
86 die "no such vm '$vmid'" if !defined($conf);
87 die "vm '$vmid' on wrong node" if $conf->{node
} ne $node;
92 my $pve_qemuserver_module = Test
::MockModule-
>new('PVE::QemuServer');
94 my $pve_qemuconfig_module = Test
::MockModule-
>new('PVE::QemuConfig');
96 my $mocked_lxc_load_conf = sub {
97 my ($class, $vmid, $node) = @_;
99 $node = $mocked_nodename if !$node;
101 my $conf = $mocked_ct_configs->{$vmid};
103 die "no such ct '$vmid'" if !defined($conf);
104 die "ct '$vmid' on wrong node" if $conf->{node
} ne $node;
109 my $pve_lxc_config_module = Test
::MockModule-
>new('PVE::LXC::Config');
111 my $mocked_replication_config = sub {
113 my $res = clone
($mocked_replication_jobs);
115 return bless { ids
=> $res }, 'PVE::ReplicationConfig';
118 my $mocked_storage_config = {
127 path
=> "/var/lib/vz",
131 pool
=> 'nonexistent-testpool',
141 my $pve_storage_module = Test
::MockModule-
>new('PVE::Storage');
143 my $mocked_storage_content = {};
145 sub register_mocked_volid
{
146 my ($volid, $snapname) = @_;
148 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid);
149 my $scfg = $mocked_storage_config->{ids
}->{$storeid} ||
150 die "no such storage '$storeid'\n";
152 my $d = $mocked_storage_content->{$storeid}->{$volname} //= {};
154 $d->{$snapname} = 1 if $snapname;
157 my $mocked_volume_snapshot_list = sub {
158 my ($cfg, $volid, $prefix) = @_;
160 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid);
163 if (my $d = $mocked_storage_content->{$storeid}->{$volname}) {
170 my $mocked_volume_snapshot = sub {
171 my ($cfg, $volid, $snap) = @_;
173 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid);
175 my $d = $mocked_storage_content->{$storeid}->{$volname};
176 die "no such volid '$volid'\n" if !$d;
180 my $mocked_volume_snapshot_delete = sub {
181 my ($cfg, $volid, $snap, $running) = @_;
183 my ($storeid, $volname) = PVE
::Storage
::parse_volume_id
($volid);
184 my $d = $mocked_storage_content->{$storeid}->{$volname};
185 die "no such volid '$volid'\n" if !$d;
186 delete $d->{$snap} || die "no such snapshot '$snap' on '$volid'\n";
189 my $pve_replication_module = Test
::MockModule-
>new('PVE::Replication');
191 my $mocked_job_logfile_name = sub {
194 return ".mocked_replication_log_$jobid";
197 my $mocked_log_time = 0;
199 my $mocked_get_log_time = sub {
200 return $mocked_log_time;
204 $pve_replication_module->mock(job_logfile_name
=> $mocked_job_logfile_name);
205 $pve_replication_module->mock(get_log_time
=> $mocked_get_log_time);
207 $pve_storage_module->mock(config
=> sub { return $mocked_storage_config; });
208 $pve_storage_module->mock(volume_snapshot_list
=> $mocked_volume_snapshot_list);
209 $pve_storage_module->mock(volume_snapshot
=> $mocked_volume_snapshot);
210 $pve_storage_module->mock(volume_snapshot_delete
=> $mocked_volume_snapshot_delete);
212 $pve_replicationconfig->mock(new
=> $mocked_replication_config);
213 $pve_qemuserver_module->mock(check_running
=> sub { return 0; });
214 $pve_qemuconfig_module->mock(load_config
=> $mocked_qemu_load_conf);
216 $pve_lxc_config_module->mock(load_config
=> $mocked_lxc_load_conf);
219 $pve_cluster_module->mock(
220 get_ssh_info
=> $mocked_get_ssh_info,
221 ssh_info_to_command
=> $mocked_ssh_info_to_command,
222 get_vmlist
=> sub { return $mocked_vmlist->(); });
223 $pve_inotify_module->mock('nodename' => sub { return $mocked_nodename; });
226 # code to generate/conpare test logs
236 $filename = basename
($0);
237 if ($filename =~ m/^(\S+)\.pl$/) {
238 $filename = "$1.log";
240 die "unable to compute log name for $0";
244 die "log already open" if defined($logname);
246 open (my $fh, ">", "$filename.tmp") ||
247 die "unable to open log - $!";
249 $logname = $filename;
258 my $diff = `diff -u '$logname' '$logname.tmp'`;
260 warn "got unexpeted output\n";
261 print "# diff -u '$logname' '$logname.tmp'\n";
266 rename("$logname.tmp", $logname) || die "rename log failed - $!";
272 # helper to track job status
276 $mocked_log_time = $ctime;
282 print $logfh "$msg\n";
286 $status = PVE
::Replication
::job_status
();
287 foreach my $jobid (sort keys %$status) {
288 my $jobcfg = $status->{$jobid};
289 $logmsg->("$ctime $jobid: new job next_sync => $jobcfg->{next_sync}");
293 PVE
::Replication
::run_jobs
($ctime, $logmsg);
295 my $new = PVE
::Replication
::job_status
();
297 # detect removed jobs
298 foreach my $jobid (sort keys %$status) {
299 if (!$new->{$jobid}) {
300 $logmsg->("$ctime $jobid: vanished job");
304 foreach my $jobid (sort keys %$new) {
305 my $jobcfg = $new->{$jobid};
306 my $oldcfg = $status->{$jobid};
308 $logmsg->("$ctime $jobid: new job next_sync => $jobcfg->{next_sync}");
309 next; # no old state to compare
311 foreach my $k (qw(target guest vmtype next_sync)) {
313 if ($oldcfg->{$k} ne $jobcfg->{$k}) {
314 $changes .= ', ' if $changes;
315 $changes .= "$k => $jobcfg->{$k}";
317 $logmsg->("$ctime $jobid: changed config $changes") if $changes;
321 my $oldstate = $oldcfg->{state};
323 my $state = $jobcfg->{state};
326 foreach my $k (qw(last_node last_try last_sync fail_count error)) {
327 if (($oldstate->{$k} // '') ne ($state->{$k} // '')) {
328 my $value = $state->{$k} // '';
330 $changes .= ', ' if $changes;
331 $changes .= "$k => $value";
334 $logmsg->("$ctime $jobid: changed state $changes") if $changes;
336 my $old_storeid_list = $oldstate->{storeid_list
};
337 my $storeid_list = $state->{storeid_list
};
339 my $storeid_list_changes = 0;
340 foreach my $storeid (@$storeid_list) {
341 next if grep { $_ eq $storeid } @$old_storeid_list;
342 $storeid_list_changes = 1;
345 foreach my $storeid (@$old_storeid_list) {
346 next if grep { $_ eq $storeid } @$storeid_list;
347 $storeid_list_changes = 1;
350 $logmsg->("$ctime $jobid: changed storeid list " . join(',', @$storeid_list))
351 if $storeid_list_changes;