#TODO RHEL support
#TODO inteligent detection of success
#Detection of base ip?

require 'facter'
require 'getoptlong'
require 'English'

apply=false
debug=false
verbose=false
version='1.0'
exitcode=0

opts = GetoptLong.new(
    ["--help",    "-h",   GetoptLong::NO_ARGUMENT],
    ["--debug",   "-d",   GetoptLong::NO_ARGUMENT],
    ["--verbose", "-v",   GetoptLong::NO_ARGUMENT],
    ["--version", "-V",   GetoptLong::NO_ARGUMENT],    
    ["--apply",   "-a",   GetoptLong::NO_ARGUMENT]       
)


def printUsage(error_code=1)
    print $0, "--debug","--version","--apply(syncronise interfaces file with live interfaces"
    puts "N.B apply will bring down interfaces that aren't in the interfaces file"
    puts "without apply the script just diffs the current live vifs and the interface file"
    puts "Only auto interfaces are read, debian only at the moment"
    exit(error_code)
end    


begin
    opts.each do |opt, arg|
        case opt
            when "--help"
                 printUsage
            when "--debug"
                 debug=true
            when "--version"
                 print "version is:", version
                 puts
                 exit(1)
            when "--apply"
                 apply=true
            when "--verbose"
                 verbose=true
        end
    end
end

printUsage unless Facter.value('operatingsystem') == 'Debian' 


#reads a file or runs a command, performs a regex on that output and returns the matches as a sorted alphabetical array
#regex in single quotes filename in doubles
def readFileToolMatchToArray(filename,regex,debug=false)
    matches = Array.new

    if File.executable?(filename)
        puts "file is executable running command" if debug
        #create a string from the commands stdout
        `#{filename}`.each_line do |line|
            matches.push($1) if line =~ /#{regex}/i
        end    

    else
        puts "reading file" if debug
        #reads file line by line
        IO.foreach(filename) do |line|
            matches.push($1) if line =~ /#{regex}/i 
        end
    end

    #sort alphabetically
    matches.sort
    matches 
end

#make sure current interfaces match those specified in the interface file.
def interfaceSync(interfaces_file,interfaces_current,apply=false)

    vifs_to_bring_down = interfaces_current-interfaces_file
    exitcode = 1 if vifs_to_bring_down.length #tell us if we're going to do something
    vifs_to_bring_down.each do |vif_not_in_interface_file|
        print "If --apply specified bring down ", vif_not_in_interface_file , " which is live but not in interface file\n"
        `/sbin/ifdown #{vif_not_in_interface_file}` if apply
    end
    vifs_to_bring_up = interfaces_file-interfaces_current
    exitcode = 2 if vifs_to_bring_up.length > 1  #tell us if we're going to do something
    vifs_to_bring_up.each do |new_vif_in_interface_file|
        print "If --apply specified bring up ", new_vif_in_interface_file, " which is in interface file but not live\n"
        `/sbin/ifup #{new_vif_in_interface_file}` if apply
    end    

end    

interfaces_file = readFileToolMatchToArray("/etc/network/interfaces",'^auto.\s*(\S*)')
interfaces_current = readFileToolMatchToArray("/sbin/ifconfig",'^([\w\d\:]+)')

puts "interfaces file contains:" , interfaces_file if debug
puts "current up interfaces are:" , interfaces_current if debug

interfaceSync(interfaces_file,interfaces_current,apply)
exit(exitcode)