# cluster-copy-lib.pl # XXX add to released modules list BEGIN { push(@INC, ".."); }; use WebminCore; &init_config(); &foreign_require("cron", "cron-lib.pl"); &foreign_require("mailboxes", "mailboxes-lib.pl"); $cron_cmd = "$module_config_directory/copy.pl"; $copies_dir = "$module_config_directory/copies"; # list_copies() # Returns an array of scheduled copies to multiple servers sub list_copies { local (@rv, $f); opendir(DIR, $copies_dir); foreach $f (sort { $a cmp $b } readdir(DIR)) { next if ($f !~ /^(\S+)\.copy$/); push(@rv, &get_copy($1)); } closedir(DIR); return @rv; } # get_copy(id) sub get_copy { local %copy; &read_file("$copies_dir/$_[0].copy", \%copy) || return undef; $copy{'id'} = $_[0]; if (!defined($copy{'email'})) { # compat - continue email to root $copy{'email'} = "root"; } return \%copy; } # save_copy(©) sub save_copy { $_[0]->{'id'} ||= time().$$; mkdir($copies_dir, 0700); &lock_file("$copies_dir/$_[0]->{'id'}.copy"); &write_file("$copies_dir/$_[0]->{'id'}.copy", $_[0]); &unlock_file("$copies_dir/$_[0]->{'id'}.copy"); } # delete_copy(©) sub delete_copy { &lock_file("$copies_dir/$_[0]->{'id'}.copy"); unlink("$copies_dir/$_[0]->{'id'}.copy"); &unlock_file("$copies_dir/$_[0]->{'id'}.copy"); } # run_cluster_job(&job, &callback) # Runs a cluster cron job on all configured servers, and for each result calls # the callback function with parameters 0/1, a server object, and the list of # files copied or an error message sub run_cluster_job { local @rv; local $func = $_[1]; # Work out which servers to run on &foreign_require("servers", "servers-lib.pl"); local @servers = &servers::list_servers_sorted(); local @groups = &servers::list_all_groups(\@servers); local @run; foreach $s (split(/\s+/, $_[0]->{'servers'})) { if ($s =~ /^group_(.*)$/) { # All members of a group ($group) = grep { $_->{'name'} eq $1 } @groups; foreach $m (@{$group->{'members'}}) { push(@run, grep { $_->{'host'} eq $m && $_->{'user'} } @servers); } } elsif ($s eq '*') { # This server push(@run, ( { 'desc' => $text{'edit_this'} } )); } elsif ($s eq 'ALL') { # All servers with login push(@run, grep { $_->{'user'} } @servers); } else { # A single remote server push(@run, grep { $_->{'host'} eq $s } @servers); } } @run = &unique(@run); # Setup error handler for down hosts sub inst_error { $inst_error_msg = join("", @_); } &remote_error_setup(\&inst_error); # Run the pre command on local if ($_[0]->{'before'} && $_[0]->{'beforelocal'}) { &system_logged("$_[0]->{'before'} >/dev/null 2>&1"); } # Run one each one in parallel and display the output $p = 0; foreach $s (@run) { local ($rh = "READ$p", $wh = "WRITE$p"); pipe($rh, $wh); select($wh); $| = 1; select(STDOUT); if (!fork()) { # Run the command in a subprocess close($rh); if (!$s->{'fast'}) { print $wh &serialise_variable( [ 0, "Fast RPC mode must be enabled ". "for copies to work" ]); exit; } &remote_foreign_require($s->{'host'}, "webmin", "webmin-lib.pl"); if ($inst_error_msg) { # Failed to contact host .. print $wh &serialise_variable([ 0, $inst_error_msg ]); exit; } # Run the pre command on remote local $bout; if ($_[0]->{'before'} && !$_[0]->{'beforelocal'}) { $bout = &remote_foreign_call($s->{'host'}, "webmin", "backquote_logged", $_[0]->{'before'}); } # Work out which files to transfer, and which directories # to create local @allnames = split(/\t+/, $_[0]->{'files'}); local (@allfiles, @alldirs); foreach $f (@allnames) { if (-d $f) { # Expand this directory &expand_dir($f, \@allfiles, \@alldirs); } else { push(@allfiles, $f); } } # Create each of the needed directories local (@errs, $d); foreach $d (@alldirs) { local $dest; if ($_[0]->{'dmode'}) { # Relative to directory $d =~ /([^\/]+)$/; $dest = $_[0]->{'dest'}."/".$1; } else { # Full path under directory $dest = $_[0]->{'dest'}.$d; } local $qdest = quotemeta($dest); local $rmd = &remote_eval($s->{'host'}, "webmin", "-d \"$qdest\" ? \"already\" : &make_dir(\"$qdest\", 0755, 1) ? undef : \$!"); if (!$rmd) { push(@dirs, $d); } elsif ($rmd ne "already") { push(@errs, [ $d, "Failed to create $dest : $rmd" ]); } } # Transfer each of the files, and make sure each was done OK local (@files, $f); foreach $f (@allfiles) { local $dest; if ($_[0]->{'dmode'}) { # Relative to directory $f =~ /([^\/]+)$/; $dest = $_[0]->{'dest'}."/".$1; } else { # Full path under directory $dest = $_[0]->{'dest'}.$f; } if (!-r $f) { push(@errs, [ $f, "Source file not found" ]); next; } if (&simplify_path($f) eq &simplify_path($dest) && $s->{'id'} == 0) { push(@errs, [ $f, "Cannot overwrite same file on this server" ]); next; } &remote_write($s->{'host'}, $f, $dest); if ($inst_error_msg) { push(@errs, [ $f, "Copy failed : $inst_error_msg" ]); next; } local $qdest = quotemeta($dest); local $rst = &remote_eval($s->{'host'}, "webmin", "[ stat(\"$qdest\") ]"); local @st = stat($f); if ($st[7] == $rst->[7]) { push(@files, $f); } else { push(@errs, [ $f, "Copy was incomplete" ]); } # Preserve file permissions &remote_foreign_call($s->{'host'}, "webmin", "set_ownership_permissions", $st[4], $st[5], $st[2] & 0777, $dest); } # Run the post command on remote local $out; if ($_[0]->{'cmd'} && !$_[0]->{'cmdlocal'}) { $out = &remote_foreign_call($s->{'host'}, "webmin", "backquote_logged", $_[0]->{'cmd'}); } print $wh &serialise_variable([ 1, \@files, \@errs, \@dirs, $out, $bout ]); close($wh); exit; } close($wh); $p++; } # Get back all the results $p = 0; foreach $s (@run) { local $rh = "READ$p"; local $line = <$rh>; close($rh); local $rv = &unserialise_variable($line); if (!$line) { &$func(0, $s, "Unknown reason"); } else { &$func($rv->[0], $s, $rv->[1], $rv->[2], $rv->[3], $rv->[4], $rv->[5]); } $p++; } unlink($ltemp); # Run the post command on local if ($_[0]->{'cmd'} && $_[0]->{'cmdlocal'}) { &system_logged("$_[0]->{'cmd'} >/dev/null 2>&1"); } return @run; } # find_cron_job(©) sub find_cron_job { local @jobs = &cron::list_cron_jobs(); local ($job) = grep { $_->{'user'} eq 'root' && $_->{'command'} eq "$cron_cmd $_[0]->{'id'}" } @jobs; return $job; } # expand_dir(dir, &files, &dirs) sub expand_dir { push(@{$_[2]}, $_[0]); opendir(DIR, $_[0]); local $f; foreach $f (readdir(DIR)) { next if ($f eq "." || $f eq ".."); local $fp = "$_[0]/$f"; next if (-l $fp); if (-d $fp) { &expand_dir($fp, $_[1], $_[2]); } else { push(@{$_[1]}, $fp); } } closedir(DIR); } 1;
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
help | Folder | 0755 |
|
|
images | Folder | 0755 |
|
|
lang | Folder | 0755 |
|
|
CHANGELOG | File | 1.02 KB | 0644 |
|
cluster-copy-lib.pl | File | 6.67 KB | 0755 |
|
config | File | 12 B | 0644 |
|
config.info | File | 83 B | 0644 |
|
config.info.ca | File | 107 B | 0644 |
|
config.info.de | File | 84 B | 0644 |
|
config.info.fr | File | 107 B | 0644 |
|
config.info.hu | File | 0 B | 0644 |
|
config.info.ms | File | 86 B | 0644 |
|
config.info.nl | File | 93 B | 0644 |
|
config.info.no | File | 95 B | 0644 |
|
config.info.pl | File | 90 B | 0644 |
|
copy.pl | File | 1.8 KB | 0755 |
|
delete.cgi | File | 507 B | 0755 |
|
edit.cgi | File | 2.67 KB | 0755 |
|
exec.cgi | File | 2.02 KB | 0755 |
|
index.cgi | File | 1.89 KB | 0755 |
|
log_parser.pl | File | 704 B | 0755 |
|
module.info | File | 172 B | 0644 |
|
module.info.af | File | 0 B | 0644 |
|
module.info.af.auto | File | 135 B | 0644 |
|
module.info.ar | File | 0 B | 0644 |
|
module.info.ar.auto | File | 179 B | 0644 |
|
module.info.be | File | 0 B | 0644 |
|
module.info.be.auto | File | 213 B | 0644 |
|
module.info.bg | File | 0 B | 0644 |
|
module.info.bg.auto | File | 235 B | 0644 |
|
module.info.ca | File | 156 B | 0644 |
|
module.info.cs | File | 41 B | 0644 |
|
module.info.cs.auto | File | 95 B | 0644 |
|
module.info.da | File | 0 B | 0644 |
|
module.info.da.auto | File | 124 B | 0644 |
|
module.info.de | File | 126 B | 0644 |
|
module.info.el | File | 0 B | 0644 |
|
module.info.el.auto | File | 273 B | 0644 |
|
module.info.es | File | 36 B | 0644 |
|
module.info.es.auto | File | 113 B | 0644 |
|
module.info.eu | File | 0 B | 0644 |
|
module.info.eu.auto | File | 145 B | 0644 |
|
module.info.fa | File | 0 B | 0644 |
|
module.info.fa.auto | File | 213 B | 0644 |
|
module.info.fi | File | 0 B | 0644 |
|
module.info.fi.auto | File | 134 B | 0644 |
|
module.info.fr | File | 40 B | 0644 |
|
module.info.fr.auto | File | 109 B | 0644 |
|
module.info.he | File | 0 B | 0644 |
|
module.info.he.auto | File | 146 B | 0644 |
|
module.info.hr | File | 0 B | 0644 |
|
module.info.hr.auto | File | 139 B | 0644 |
|
module.info.hu | File | 35 B | 0644 |
|
module.info.hu.auto | File | 99 B | 0644 |
|
module.info.it | File | 0 B | 0644 |
|
module.info.it.auto | File | 129 B | 0644 |
|
module.info.ja | File | 0 B | 0644 |
|
module.info.ja.auto | File | 190 B | 0644 |
|
module.info.ko | File | 0 B | 0644 |
|
module.info.ko.auto | File | 144 B | 0644 |
|
module.info.lt | File | 0 B | 0644 |
|
module.info.lt.auto | File | 141 B | 0644 |
|
module.info.lv | File | 0 B | 0644 |
|
module.info.lv.auto | File | 136 B | 0644 |
|
module.info.ms | File | 127 B | 0644 |
|
module.info.mt | File | 0 B | 0644 |
|
module.info.mt.auto | File | 140 B | 0644 |
|
module.info.nl | File | 38 B | 0644 |
|
module.info.nl.auto | File | 106 B | 0644 |
|
module.info.no | File | 30 B | 0644 |
|
module.info.no.auto | File | 101 B | 0644 |
|
module.info.pl | File | 120 B | 0644 |
|
module.info.pt | File | 0 B | 0644 |
|
module.info.pt.auto | File | 147 B | 0644 |
|
module.info.pt_BR | File | 0 B | 0644 |
|
module.info.pt_BR.auto | File | 153 B | 0644 |
|
module.info.ro | File | 0 B | 0644 |
|
module.info.ro.auto | File | 147 B | 0644 |
|
module.info.ru | File | 0 B | 0644 |
|
module.info.ru.auto | File | 230 B | 0644 |
|
module.info.sk | File | 0 B | 0644 |
|
module.info.sk.auto | File | 132 B | 0644 |
|
module.info.sl | File | 0 B | 0644 |
|
module.info.sl.auto | File | 118 B | 0644 |
|
module.info.sv | File | 0 B | 0644 |
|
module.info.sv.auto | File | 135 B | 0644 |
|
module.info.th | File | 0 B | 0644 |
|
module.info.th.auto | File | 320 B | 0644 |
|
module.info.tr | File | 0 B | 0644 |
|
module.info.tr.auto | File | 148 B | 0644 |
|
module.info.uk | File | 0 B | 0644 |
|
module.info.uk.auto | File | 216 B | 0644 |
|
module.info.ur | File | 0 B | 0644 |
|
module.info.ur.auto | File | 195 B | 0644 |
|
module.info.vi | File | 0 B | 0644 |
|
module.info.vi.auto | File | 137 B | 0644 |
|
module.info.zh | File | 0 B | 0644 |
|
module.info.zh.auto | File | 115 B | 0644 |
|
module.info.zh_TW | File | 0 B | 0644 |
|
module.info.zh_TW.auto | File | 121 B | 0644 |
|
save.cgi | File | 2.1 KB | 0755 |
|
uninstall.pl | File | 230 B | 0755 |
|