#!/usr/bin/perl
#
# Copyright 2025 Citrix Systems, Inc. All rights reserved.
# This software and documentation contain valuable trade
# secrets and proprietary property belonging to Citrix Systems, Inc.
# None of this software and documentation may be copied,
# duplicated or disclosed without the express
# written permission of Citrix Systems, Inc.
#

use Sys::Syslog;

$debug_print            = 0;
$varstr                 = "/var";
$varpath                = "$varstr/netscaler";
$guidir                 = "gui";
$nitropath              = "$varpath/nitro";
$state_file_post_reboot = "$varstr/nsinstall/installns_state_post_reboot";
$variant                = "$ENV{NSVARIANT}";

#options for syslogging the installation activity
$syslog_ident    = "installns: ";
$syslog_opt      = "ndelay,pid,nofatal,perror";
$syslog_facility = "LOG_USER";
$syslog_level    = "LOG_NOTICE";

#write a string to the system log
sub log_to_syslog {
    my $log_msg = $_[0];
    syslog $syslog_level, "%s", $log_msg;
}

sub log_status {
    my $log_msg = $_[0];

    print "$log_msg\n";
    log_to_syslog($log_msg);
}

#write a string to the state log and the syslog. This file contains  information about the current
#install process that may later be used to restart or undo this installation
sub log_state {
    my $log_msg = $_[0];

    print STATE_LOG "$log_msg\n";
    log_to_syslog($log_msg);
}

#print trace messages about subroutine execution
#goes to syslog and to standard output. mostly for developer use.
sub log_trace {
    my $log_msg = $_[0];

    if ($debug_print) {
        log_status($log_msg);
    }
}

# New function to finalize GUI installation by moving gui_new to gui
sub finalize_gui_installation {
    my $this_subroutine_name = ( caller(0) )[3];
    my $ret;

    log_trace " \nBEGIN $this_subroutine_name";
    
    if ( -d "$varpath/gui_new" ) {
        log_status "Finalizing GUI installation...";
        
        # Remove existing gui directory if it exists
        if ( -d "$varpath/$guidir" ) {
            $ret = system("rm -rf $varpath/$guidir");
            if ($ret != 0) {
                log_status "Error: Unable to delete the existing $varpath/$guidir directory. GUI installation could not be finalized.";
                return;
            }
        }
        
        # Move gui_new to gui
        $ret = system("mv $varpath/gui_new $varpath/$guidir");
        if ($ret != 0) {
            log_status "Error: Unable to move $varpath/gui_new to $varpath/$guidir. GUI installation could not be finalized.";
            return;
        }

        log_status "GUI installation finalized successfully.";
    } else {
        log_trace "No gui_new directory found, skipping GUI finalization.";
    }
    
    log_trace "END $this_subroutine_name";
} ## end sub finalize_gui_installation

sub install_python_nitro {
    my $this_subroutine_name = ( caller(0) )[3];
    my $errs;
    my $python_sdk;
    log_trace " \nBEGIN $this_subroutine_name";
    log_status "Extracting python nitro...";
    if ( -f "$nitropath/nitro-python.tgz" ) {
       `tar xvpfz $nitropath/nitro-python.tgz -C $nitropath 2>> ./err_msg`;
        if ( -f "./err_msg" && $debug_print ) {
            $errs = `cat ./err_msg`;
            log_status $errs;
        }
       `tar -xpf $nitropath/ns_nitro-python_*.tar -C $nitropath`;
       $python_sdk = glob "$nitropath/nitro-python-*";
       if ( -e $python_sdk ) {
          `cd $python_sdk; /var/python/bin/python ./setup.py install; cd  ..`;
#  Clean up Python PY files
          `rm -rf  $python_sdk`;
       }
    log_status "Extracting python nitro... done";
   }
    log_trace "END $this_subroutine_name";
} ## end sub nstall_nitro_python

sub install_cloudautoscale {
    my $this_subroutine_name = ( caller(0) )[3];
    my $errs;
    log_trace " \nBEGIN $this_subroutine_name";

    $rainmanpath="$varpath/rainman";

    if ( -f "./cloudautoscale.tgz" ) {
        log_status "Installing Rainman scripts...";
        `tar xfpz ./cloudautoscale.tgz -C $varpath/ 2> ./err_msg`;
    }
    if ( -f "./err_msg" && $debug_print ) {
        $errs = `cat ./err_msg`;
        log_status $errs;
    }
    if ( -d "$rainmanpath" ) {
        log_status "Extracting cloud autoscale...";
       `cd $rainmanpath; /var/python/bin/python $rainmanpath/setup.py install 2>> ./err_msg`;
        if ( -f "./err_msg" && $debug_print ) {
            $errs = `cat ./err_msg`;
            log_status $errs;
        }
        `cd; rm -rf $rainmanpath`
    }
    log_status "Done Extracting cloud autoscale...";
    log_trace "END $this_subroutine_name";
} ## end sub install_cloudautoscale

sub install_cloudhadaemon {
    my $this_subroutine_name = ( caller(0) )[3];
    my $errs;
    log_trace " \nBEGIN $this_subroutine_name";

    $cloudhadaemonpath="$varpath/cloudhadaemon";

    if ( -f "./cloudhadaemon.tgz" ) {
        log_status "Installing cloudhadaemon scripts...";
        `tar xfpz ./cloudhadaemon.tgz -C $varpath/ 2> ./err_msg`;
    }
    if ( -f "./err_msg" && $debug_print ) {
        $errs = `cat ./err_msg`;
        log_status $errs;
    }
    if ( -d "$cloudhadaemonpath" ) {
        log_status "Extracting cloudhadaemon...";
        `cd $cloudhadaemonpath; /var/python/bin/python $cloudhadaemonpath/setup.py install 2>> ./err_msg`;
        if ( -f "./err_msg" && $debug_print ) {
            $errs = `cat ./err_msg`;
            log_status $errs;
        }
        `cd; rm -rf $cloudhadaemonpath`;
    }
    log_status "Done Extracting cloudhadaemon...";
    log_trace "END $this_subroutine_name";
} ## end sub install_cloudhadaemon

sub install_azureautoconfig
{
	my $this_subroutine_name = ( caller(0) )[3];
	my $errs;
	log_trace " \nBEGIN $this_subroutine_name";
	my $configpath = "$varpath/azureautoconfig";
	if ( -f "./azureautoconfig.tgz" )
	{
		log_status "Azure Auto Config Script untarring";
		`tar xfpz ./azureautoconfig.tgz -C $varpath/ 2> ./err_msg`;
		if ( -f "./err_msg" ) {
			$errs = `cat ./err_msg`;
			log_status $errs;
			`rm -rf ./err_msg`;
		}
	}
	else
	{
		log_status "AzureAutoConfig script tar not found";
	}
	if ( -d "$configpath" )
	{
		log_status "Installing AzureAutoConfig script";
		`cd $configpath; /var/python/bin/python $configpath/setup.py install 2>> ./err_msg`;
		if ( -f "./err_msg" ) {
			$errs = `cat ./err_msg`;
			log_status $errs;
			`rm -rf ./err_msg`;
		}

		`rm -rf $configpath`;
	}
	else
	{
		log_status "Not found azureautoconfig folder";
	}
    log_trace "END $this_subroutine_name";
}

sub install_azureagent
{
    my $this_subroutine_name = ( caller(0) )[3];
    my $errs;
    log_trace " \nBEGIN $this_subroutine_name";
	my $waagentconfigpath = "$varpath/azureagent";
	if ( -f "./azureagent.tgz" )
	{
		log_status "Azure Agent script untarring";
		`tar xfpz ./azureagent.tgz -C $varpath/ 2> ./err_msg`;
		if ( -f "./err_msg" ) {
			$errs = `cat ./err_msg`;
			log_status $errs;
			`rm -rf ./err_msg`;
		}
	}
	else
	{
		log_status "Azure Agent tar not found";
	}
	if ( -d "$waagentconfigpath" )
	{
		log_status "Installing Azure Agent script";
		`cd $waagentconfigpath; /var/python/bin/python $waagentconfigpath/setup.py install 2>> ./err_msg`;
		if ( -f "./err_msg" ) {
			$errs = `cat ./err_msg`;
			log_status $errs;
			`rm -rf ./err_msg`;
		}
		`mv $waagentconfigpath/waagent.conf /nsconfig/`;
		`rm -rf $waagentconfigpath`;
	}
	else
	{
		log_status "Not found Agent folder";
	}
    log_trace "END $this_subroutine_name";
}

sub compile_python_modules {
    my $this_subroutine_name = ( caller(0) )[3];
    my $errs;
    log_trace " \nBEGIN $this_subroutine_name";
    log_status "Compiling python modules...";
    `/var/python/bin/python -m compileall /var/python 2>> ./err_msg`;
    if ( -f "./err_msg" && $debug_print ) {
        $errs = `cat ./err_msg`;
        log_status $errs;
    }
    log_status "Compiling python modules... done";
    log_trace "END $this_subroutine_name";
}

open STATE_LOG, ">$state_file_post_reboot";
openlog $syslog_ident, $syslog_opt, $syslog_facility;

$date      = time();
$localdate = localtime();

log_state "BEGIN_TIME $date $localdate";

if ( $variant eq "v" ) {
    finalize_gui_installation();
    install_python_nitro();

    chomp($ret = `sysctl netscaler.vpx_on_cloud`);
    if ( $ret =~ /1$/ ) {
        #### AWS Cloud
        install_cloudautoscale();
        install_cloudhadaemon();
    } elsif ( $ret =~ /3$/ ) {
        #### Azure Cloud
        install_cloudautoscale();
        install_azureautoconfig();
        install_azureagent();
        install_cloudhadaemon();
    } elsif ( $ret =~ /4$/ ) {
        #### GCP Cloud
        install_cloudautoscale();
        install_cloudhadaemon();
    }
}

compile_python_modules();

$date      = time();
$localdate = localtime();

log_state "END_TIME $date $localdate";
close STATE_LOG;

closelog;
exit();