#!/usr/local/cpanel/3rdparty/bin/perl
use Carp ();
use XML::Simple;
use lib "/usr/local/cpanel";
use LWP::UserAgent;
require "/root/ard/readconfig.pl";
use strict;
our $VERSION = "6.2";
BEGIN {
unshift(@INC, '/usr/local/cpanel', '/scripts');
pop(@INC) if ($INC[$#INC] eq '.');
}
#use cPScript::ZoneFile ();
# where to check for new but not loaded files
# because local and remote updater may have different download list
# i need to download updater to 'tmppath' not 'localpath' because of
# its new body don't changed during updater script running.
my $updater_name = 'update.cgi';
my $updater_localpath = '';
my $updater_tmppath = '';
my $global_conf = 'global.conf';
my $global_tmppath = '';
my $global_localpath = '';
# read configuration
my $conf_file = '/root/ard/etc/global.conf';
my $Conf = &readconfig::ReadConfig ($conf_file);
my $ProjectDownloads = $Conf->{updates};
print "Content-type: text/html\n\n";
sub urlget {
my $url = shift;
my $file = shift;
my $status = 0;
my $timeout = 1200;
my $ua = LWP::UserAgent->new;
$ua->timeout(30);
my $req = HTTP::Request->new(GET => $url);
my $res;
my $text;
($status, $text) = eval {
local $SIG{__DIE__} = undef;
local $SIG{'ALRM'} = sub {die "Download timeout after $timeout seconds"};
alarm($timeout);
if ($file) {
$|=1;
my $expected_length;
my $bytes_received = 0;
my $per = 0;
my $oldper = 0;
open (OUT, ">$file\.tmp") or return (1, "Unable to open $file\.tmp: $!");
binmode (OUT);
print "...0\%\n";
$res = $ua->request($req,
sub {
my($chunk, $res) = @_;
$bytes_received += length($chunk);
unless (defined $expected_length) {$expected_length = $res->content_length || 0}
if ($expected_length) {
my $per = int(100 * $bytes_received / $expected_length);
if ((int($per / 5) == $per / 5) and ($per != $oldper)) {
print "...$per\%\n";
$oldper = $per;
}
} else {
print ".";
}
print OUT $chunk;
});
close (OUT);
print "\n";
} else {
$res = $ua->request($req);
}
alarm(0);
if ($res->is_success) {
if ($file) {
rename ("$file\.tmp","$file") or return (1, "Unable to rename $file\.tmp to $file: $!");
return (0, $file);
} else {
return (0, $res->content);
}
} else {
return (1, "Unable to download: ".$res->message);
}
};
alarm(0);
if ($@) {
return (1, $@);
}
if ($text) {
return ($status,$text);
} else {
return (1, "Download timeout after $timeout seconds");
}
}
#
# Get a database servers' configuration files from remote and plases it into $Config->{}
# Input:
# 1. local path to servers' directory;
# 2. remote url where to get servers from;
#
# Returns:
# nothing;
#
sub UpdateDBServerList($$) {
my $servers_dir = shift;
my $servers_url = shift;
my @files;
return "" if ($servers_dir eq '' or $servers_url eq '');
my $ua = LWP::UserAgent->new;
$ua->timeout(10);
$ua->env_proxy;
my $response = $ua->get($servers_url);
if ($response->is_success) {
@files = ($response->content =~ (/href="([^"]+\.conf)/g));
} else {
print "There are no servers files at $servers_url!!!<br>\n";
return "";
}
print "<BR>Removing old dbservers files...<BR>\n";
opendir (DIR, "$servers_dir");
my @oldServers = grep { ! /^\./ && ! /^\.\./ } readdir(DIR);
closedir (DIR);
foreach my $iserver (@oldServers) {
print "Removing $servers_dir/$iserver ...";
unlink "$servers_dir/$iserver";
print "Done!<BR>\n";
}
print "<BR> Downloading new dbservers files...\n";
foreach my $ifile (@files) {
print "\t\t<br>downloading file <b>$ifile</b> ...";
my ($status, $text) = &urlget("$servers_url/$ifile" , "$servers_dir/$ifile");
if ($status) {
print "\tProblems: $text<br>\n";
}
}
}
## End of functions
foreach my $k (@$ProjectDownloads) {
print("<br>Updating <b>". $k->{'url'} ."</b>...");
my ($status, $text);
if ($k->{'localpath'} eq 'SPECIAL') {
print "<br>\n";
&UpdateDBServerList ($Conf->{'servers_dir'}, $k->{'url'});
print "<br>\n";
} elsif ($k->{'url'} =~ $updater_name) {
($status, $text) = &urlget($k->{'url'} , $k->{'tmppath'});
$updater_localpath = $k->{'localpath'};
$updater_tmppath = $k->{'tmppath'};
} elsif ( $k->{'url'} =~ $global_conf ) {
($status, $text) = &urlget($k->{'url'} , $k->{'tmppath'});
$global_localpath = $k->{'localpath'};
$global_tmppath = $k->{'tmppath'};
} else {
($status, $text) = &urlget($k->{'url'} , $k->{'localpath'});
}
if ($status) {
print "Problems: $text\n";
exit;
}
chmod 0755, $k->{'localpath'};
}
#
# We should get master's IP record from old global.conf configuration file and put it into new configuration file
# and then we save new config into its file i.e. with '_tmp' suffix to compare new and old configs.
#
my $GlobalConf;
my $new_cfg;
$new_cfg = Config::Tiny->read($global_tmppath);
$GlobalConf = Config::Tiny->read($global_localpath);
print "<br><br>Updating MasterIP: <span style='color: green; font-weight: bold;'>" . unquote($GlobalConf->{slaves}->{slave_master}) . "</span>";
$new_cfg->{slaves}->{slave_master} = $GlobalConf->{slaves}->{slave_master} ;
print " Done!<br>\n";
print "<br>Saving new configuration into $global_tmppath file.... ";
$new_cfg->write($global_tmppath); # saving in current global_tmp.conf
print "Done!<br>\n";
print "<br>Re-saving current configuration into $global_localpath file.... ";
$GlobalConf->write($global_localpath); # re-saving current config global.conf. the 2 files are saved by Config::Tiny
print "Done!<br>\n";
# if size of new config and old one is different then write this;
my $configs_are_different = 0;
my $curr_conf_size = -s "$global_localpath";
my $new_conf_size = -s "$global_tmppath";
print "\ \ \ - old configuration file size <i style='color: green;'>$curr_conf_size</i> bytes<br>\n";
print "\ \ \ - new configuration file size <i style='color: green;'>$new_conf_size</i> bytes<br>\n";
if ($curr_conf_size != $new_conf_size) {
$configs_are_different++;
print "<center style='color: red;'> The configuration files are different so we must re-start update process!</center><br>\n";
}
print "<br>Saving new configuration into <i style='color:green; font-weight: bold;'>$global_localpath</i> file.... ";
$new_cfg->write($global_localpath); # saving in current global.conf
print "Done!<br>\n";
# checking 'updaters' are equal size i.e. the same
# if size of new config and old one is different then write this;
my $updaters_are_different = 0;
my $curr_updater_size = -s "$updater_localpath";
my $new_updater_size = -s "$updater_tmppath" ;
if ($curr_updater_size != $new_updater_size) {
print "<br><center>The 'updater' files are different we must restart updating process!</center><br>\n";
print "\ \ \ - current updater script's size <i style='color: red; font-weight: bold;'>$curr_updater_size</i> bytes<br>\n";
print "\ \ \ - new updater script's size <i style='color: red; font-weight: bold;'>$new_updater_size</i> bytes<br><br>\n";
$updaters_are_different++;
}
# finally i have to move updater file to it's place and set permitions allowing execution file
print "<br>Moving $updater_tmppath to $updater_localpath... <br>\n";
rename ("$updater_tmppath","$updater_localpath") or return (1, "Unable to rename $updater_tmppath to $updater_localpath: $!");
chmod 0755, $updater_localpath;
print "Done!<br><br>\n";
if ($updaters_are_different or $configs_are_different) {
print "*** <span style='color: red; font-weight: bold;'>Restarting updater process</span><br><br>\n";
system("$updater_localpath");
} else {
print "<hr><br>";
print "<span style='color: blue; text-align: center;'>Repository has been updated successfully!</span><br>\n";
}