#!/usr/bin/perl
# IBM(c) 2008 EPL license http://www.eclipse.org/legal/epl-v10.html

# Sample xCAT post script for configuring secondary adatper based on eth0 
# settings and some conventions.  This scripts works for both diskfull installs # and diskless boots.

# configiba.2ports assume two ports are both available for one IB adapter.

use Socket;

#Check the platform
my $PLTFRM = `uname`;
chomp $PLTFRM;

my $OS_name;
my $ib_driver;
if ( $ENV{OSVER} && ($ENV{OSVER} =~ /rhe(\D+)(\d+)(\.\d+)?/)  ) {
    if ( $2 > 5 ) {
        $ib_driver = "rdma";
    } else {
        $ib_driver = "openibd";
    }
} else {
    $ib_driver = "openibd";
}

my $HOST = `hostname -s`;
chomp $HOST;

my @nums = (0..1);
my @nics;
foreach my $num ( @nums ) {
    # Take primary node name, add -ib$num and then reverse resolve to get what ip should be
    my $nic = "ib$num";
    my $hostname;

    # Get hostname from system incase postscript environment is not ready
    if ( $HOST ) {
        $hostname = "$HOST-$nic";
    } else {
        $hostname = "$ENV{NODE}-$nic";
    }

    my $packed_ip = gethostbyname($hostname);
    if ( !$packed_ip ) { system("logger -t xcat 'configiba: cannot resolve $hostname.'"); next; }
    my $ip = inet_ntoa($packed_ip);
    #TODO: should contact xcatd on the service node to get the netmask and gateway from the networks table
    my $netmask = "255.255.255.0";
    my ($first, $second, $rest) = split(/\./, $ip);
    my $gateway = "$first.$second.255.254";

    if ( $PLTFRM eq "Linux" ) {
        # Issue rdma for Linux at boot time
        if ( -f '/etc/redhat-release' )
        {
            $OS_name = "redhat";
        }
        elsif ( -f '/etc/SuSE-release' )
        {
            $OS_name = "suse";
        }
        else
        {
            print "Unsupported to config IB on this OS!\n";
            exit;
        }
        if ( -f "/etc/sysctl.conf" )
        {
            updatefile("/etc/sysctl.conf", "net.ipv4.conf.$nic.arp_filter");
            updatefile("/etc/sysctl.conf", "net.ipv4.conf.$nic.arp_ignore");
            runcmd("echo 'net.ipv4.conf.$nic.arp_filter = 1' >> /etc/sysctl.conf");
            runcmd("echo 'net.ipv4.conf.$nic.arp_ignore = 1' >> /etc/sysctl.conf");
        }
        # Write the info to the ifcfg file
        my $dir;
        if ( $OS_name eq 'suse')
        {
            $dir = "/etc/sysconfig/network";
        }
        elsif ( $OS_name eq 'redhat' )
        {
            $dir = "/etc/sysconfig/network-scripts";
        }
        if ( !open(FILE, ">$dir/ifcfg-$nic") ) { system("logger -t xcat 'configiba: cannot open $dir/ifcfg-$nic.'"); exit 1; }
        print FILE "DEVICE=$nic\n";
        print FILE "BOOTPROTO=static\n";
        print FILE "IPADDR=$ip\n";
        print FILE "NETMASK=$netmask\n";
        print FILE "GATEWAY=$gateway\n";
        print FILE "ONBOOT=yes\n" if ( $OS_name eq 'redhat');
        print FILE "STARTMODE=auto\n" if ( $OS_name eq 'suse');
        close FILE;

        push @nics, $nic;
    } elsif ( $PLTFRM eq "AIX" ) {
    #Check whether the icm is available
        my $cmd = "lsdev -C | grep icm | grep Available";
        `$cmd`;
        if ($?) {
            my $iba_cmd = "mkdev -c management -s infiniband -t icm";
            runcmd($iba_cmd);
            if ($?) {
                my $iba_command = "mkdev -l icm";
                runcmd($iba_command);
                if ($?) { exit $?; }
            }
        }
        #Configure the IB interfaces
        my $iba_num = int($num / 2);
        my $ib_adapter = "iba$iba_num";
        my $port;
        if ($num % 2 ==0) { $port = 1; }
        else { $port = 2; }
        my $mkib_cmd = "mkiba -a $ip -i $nic -A $ib_adapter -p $port -P -1 -S up -m $netmask";
        runcmd($mkib_cmd);
        system("logger -t xcat 'configiba: successfully configured $nic.'");
    }
}

if ( $PLTFRM eq "Linux" ) {

    if ( -f "/etc/rdma/rdma.conf" )
    {
        updatefile("/etc/rdma/rdma.conf", "SDP_LOAD=yes", "SDP_LOAD=no");
    } elsif ( -f "/etc/infiniband/openib.conf" )
    {
        updatefile("/etc/infiniband/openib.conf", "SDP_LOAD=yes", "SDP_LOAD=no");
    }

    if ( -f "/etc/modprobe.conf" )
    {
        updatefile("/etc/modprobe.conf", "options ib_ehca nr_ports=1");
        updatefile("/etc/modprobe.conf", "options ib_ehca lock_hcalls=0");
        runcmd("echo 'options ib_ehca lock_hcalls=0' >> /etc/modprobe.conf");
    }

    my $rdma_cmd = "/sbin/chkconfig --level 2345 $ib_driver on";
    runcmd($rdma_cmd);
    my $rdma_start_cmd = "/sbin/service $ib_driver restart";
    runcmd($rdma_start_cmd);

    runcmd("sysctl -p");

    sleep(20);
    foreach my $nic ( @nics ) {
        sleep(5);
        runcmd("ifup $nic");
        system("logger -t xcat 'configiba: successfully configured $nic.'");
    }
}

#Configure the ml0 interface
if ( $PLTFRM eq "AIX" ) {
    my $hostname;
    if ( $HOST ) {
        $hostname = "$HOST-ml0";
    } else {
        $hostname = "$ENV{NODE}-ml0";
    }
    my $packed_ip = gethostbyname($hostname);
    if ( !$packed_ip ) { system("logger -t xcat 'configiba: cannot resolve $hostname.'"); exit; }
    my $ip = inet_ntoa($packed_ip);
    my $netmask = "255.255.255.0";

    #Check whether the mlt0 is available
    my $cmd = "lsdev -C | grep mlt0 | grep Available 2>&1 >/dev/null";
    `$cmd`;
    if ( $? ) {
        system("logger -t xcat 'configiba: mlt0 interface is not available'");
        exit;
    }

    #Check whether the ml0 is available
    my $lsdev_cmd = "lsdev -C | grep ml0 2>&1 >/dev/null";
    `$lsdev_cmd`;
    if ( $? ) {
        my $cfgmgr_cmd = "cfgmgr 2>&1 >/dev/null";
        `$cfgmgr_cmd`;
    }

    my $chdev_cmd = "chdev -l ml0 -a state=detach 2>&1";
    runcmd($chdev_cmd);

    $chdev_cmd = "chdev -l ml0 -a netaddr=$ip -a netmask=$netmask -a state=up 2>&1";
    runcmd($chdev_cmd);

    system("logger -t xcat 'configiba: configured ml0.'");
}

exit 0;

sub runcmd {
    my $cmd = shift @_;
    $cmd .= ' 2>&1';
    my @output = `$cmd`;
    my $rc = $? >> 8;
    if ( $rc ) {
        system("logger -t xcat 'configiba: command $cmd failed with rc $rc: " . join('',@output) . "'");
        return $rc;
    }
}

sub updatefile {
    my $fname = shift;
    my $old   = shift;
    my $new   = shift;
    unless ( open( HOSTS,"<$fname" )) {
        return undef;
    }
    my @rawdata = <HOSTS>;
    my @newdata = ();
    close( HOSTS );
    chomp @rawdata;

    foreach my $line ( @rawdata ) {
        if ( $line =~ /^(.*)$old(.*)$/ ) {
            if ( $new ) {
                push @newdata, "$1$new$2";
            }
        } else {
            push @newdata, $line;
        }
    }
    unless ( open( HOSTS,">$fname" )) {
        return undef;
    }
    for my $line (@newdata)
    {
        print HOSTS "$line\n";
    }
    close( HOSTS );
}
