Viewing File: /usr/local/cpanel/whostmgr/docroot/cgi/ardcluster/update.cgi

#!/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 "\&nbsp;\&nbsp;\&nbsp;- old configuration file size <i style='color: green;'>$curr_conf_size</i> bytes<br>\n";
print "\&nbsp;\&nbsp;\&nbsp;- 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 "\&nbsp;\&nbsp;\&nbsp; - current updater script's size <i style='color: red; font-weight: bold;'>$curr_updater_size</i> bytes<br>\n";
    print "\&nbsp;\&nbsp;\&nbsp; - 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";
}

Back to Directory File Manager