#!/usr/bin/perl
#
#

use warnings;
use strict;

use lib '../include';

use Net::Telnet::Cisco;
use Net::Ping;

use Data::Dumper;

my $patchlist = "/root/patchlist.txt";
my $switches = "/root/switches.txt";
#my $patchlist = "/home/eirikn/patchlist.txt.eirik";
#my $switches = "/home/eirikn/switches.txt.eirik";
#my $patchlist = "/root/patchlist.txt.d05";
#my $switches = "/root/switches.txt.d05";

open LOG, ">>/tmp/zyxel.could.not.connect" or die "Could not open log";


BEGIN {
	require "../include/config.pm";
	eval {
		require "../include/config.local.pm";
	};
}

sub ios_getroute {
	my ($t, $net) = @_;

	$t->cmd("show ip route".($net ? " $net" : '')) or return 0;;
	
	return 1;
}

#my $ios_server = "noc-gw.net.tg07.gathering.org";
#my $vlannumber = 16;

#my $ios = nms::ios_connect($ios_server, $nms::config::ios_user, $nms::config::ios_pass)
#	or die "Unable to connect to cisco";


sub start_vlan {
	my ($ios, $vlan) = @_;

	$ios->cmd("conf t");
	$ios->cmd("int vlan $vlan");
	$ios->cmd("ip add 192.168.1.254 255.255.255.0 secondary");
	$ios->cmd("exit");
	$ios->cmd("exit");
}

sub stop_vlan {
	my ($ios, $vlan) = @_;

	$ios->cmd("conf t");
	$ios->cmd("int vlan $vlan");
	$ios->cmd("no ip add 192.168.1.254 255.255.255.0 secondary");
	$ios->cmd("exit");
	$ios->cmd("exit");
}



sub do_distro {
	my ($dip, $newip, $vlan, $switchname) = @_;

	my $ios = Net::Telnet::Cisco->new(Host => $dip,
			Errmode => 'return',
			Prompt => '/\S+[#>]/');
#			Prompt => '/[^\s\(]+(\([^\(]\)){0,1}[#>]/');
	if (!defined($ios)) {
		print "Could not connect to $dip";
		return 0;
	}
	$ios->login($nms::config::ios_user, $nms::config::ios_pass);
	$ios->enable;

#nms::ios_enable($ios);
#$ios->cmd();
#nms::ios_getroute($ios, "192.168.1.0");
#$ios->cmd("");

#nms::ios_close($ios);

# Disable paging
	$ios->cmd("terminal length 0");

#my @routes = $ios->cmd("show ip route");

	if (ios_getroute($ios, "192.168.1.0") == 1) {
		print "Already routed up 192.168.1.0/24\n" ;
		return 0;
	}

	my $zyxeloldip = "192.168.1.1";
	start_vlan($ios, $vlan);

### Do things
## ZyxelNG connect

	my $p = Net::Ping->new();
	printf "Waiting for zyxel to come up...\n";
	my $counter = 0;
	while (1) {
		if ($counter > 6) {
			print "Waiting for zyxel on $dip:$vlan timed out, wanted to set ip: $newip\n";
			print LOG "Could not connect to $switchname\n";
			stop_vlan($ios, $vlan);
			return 0;
		}
		last if $p->ping($zyxeloldip);
		print "pinging...\n";
		sleep 1;
		$counter++;
	}
	print "Zyxel is alive..\n";
	$p->close();

	system("perl ./zyxelng.pl 192.168.1.1 $newip $switchname");

####

	stop_vlan($ios, $vlan);


	$ios->close();

	return 1;
}

## Collect switch ips

my %switchips;

open(SWITCHES, $switches) or die "Unable to open switches";
while(<SWITCHES>) {
	my ($ip, $net, $name) = split;

	if ($name =~ /e\d+-\d/) {
		die "We only support /26 nets for now you wanted $net" if ($net ne "26");
		$switchips{$name} = $ip;
	}
}
close(SWITCHES);

sub switch_info {
	my ($switch, $distro, $port) = @_;

	$switch =~ /e(\d+)-(\d)/;
	my ($row, $place) = ($1, $2);
	my $ipnet = $switchips{$switch};
	my $vlan = $row . $place;
	my ($first, $second, $third, $fourth) = split(/\./, $ipnet);
	my $ip = "$first.$second.$third.".(int($fourth)+2);
	my $dip = $distro.".net.tg07.gathering.org";

	return ($row, $place, $ipnet, $vlan, $ip, $dip);
}

sub first_run {

	open(PATCHLIST, $patchlist) or die "Unable to open patchlist";
	while (<PATCHLIST>) {
		my ($switch, $distro, $port) = split;

		#print "Testing: ".$ARGV[1]." $switch\n";
		next if (defined($ARGV[1]) and $ARGV[1] ne $switch);
		
		print "First run...\n";
		my ($row, $place, $ipnet, $vlan, $ip, $dip) = switch_info($switch, $distro, $port);
		print "Switch: $switch, Distro: $distro, vlan: $vlan\n";
		print "Ip net: $ipnet\n";
		print "Ip: $ip\n";

		do_distro($dip, $ip, $vlan, $switch);
#	my ($dip, $newip, $vlan) = @_;
	}
	close(PATCHLIST);
}

sub verify_run {
	open(PATCHLIST, $patchlist) or die "Unable to open patchlist";
	while (<PATCHLIST>) {
		print "Verify run....\n";
		my ($switch, $distro, $port) = split;

		if ($switch eq "e71-6") {
			print "There is no e71-6\n";
			next;
		}
		
		my ($row, $place, $ipnet, $vlan, $ip, $dip) = switch_info($switch, $distro, $port);
		print "Switch: $switch, Distro: $distro, vlan: $vlan\n";
		print "Ip net: $ipnet\n";
		print "Ip: $ip\n";

		my $p = Net::Ping->new();
		printf "Checking if zyxel is up $dip:$vlan $ip...\n";
		my $counter = 0;
		while (1) {
			if ($counter > 4) {
				print "No answer from $dip:$vlan $ip, trying to route it up\n";
				my $ret = do_distro($dip, $ip, $vlan, $switch);
				if ($ret == 0) {
					# No answer from zyxel
					last;
				}
				print "Waiting for telnet to time out so we can do run ciscong.pl\n";
				sleep 100;
				system("perl ./ciscong2.pl $switch");
				last;
			}
			last if $p->ping($ip);
			print "pinging...\n";
			sleep 1;
			$counter++;
		}

#	my ($dip, $newip, $vlan) = @_;
	}
	close(PATCHLIST);
}


if ($#ARGV > -1) {
	first_run();
}
else {
	verify_run();
}

close(LOG);


