#!/usr/bin/perl 
# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
# vim: ts=4 sts=4 sw=4:

#ident "$Id: assign-default-networks,v 1.1 2015/05/21 08:07:23 carsten.kuhl Exp $
# Copyright (c) 2014 Bruker BioSpin GmbH"";

use strict;
use warnings;
use English;
use Getopt::Long;
use File::Basename;
use File::Spec;
use File::Find ();
use Pod::Usage;
use Sys::Syslog qw(:standard :macros);  # standard functions & macros
use Data::Dumper;
use Time::localtime;

my $program = basename($0);

die "Only root may run $program\n" unless $EFFECTIVE_USER_ID == 0;

sub ShowHashArray($%);
sub setMacAdress($$);
sub get_os_version();

# for the convenience of &wanted calls, including -eval statements:
use vars qw/*name *dir *prune/;
*name   = *File::Find::name;
*dir    = *File::Find::dir;
*prune  = *File::Find::prune;

####
# Supported options
my $help = 0;
my $man = 0;
my $syslog = 1;
my $verbose = 0;

GetOptions(
	   'help|?' => \$help,
	   'man'  => \$man,
	   'verbose+'  => \$verbose,
	   'syslog!'  => \$syslog
	  ) || pod2usage(2);
pod2usage(1) if $help;
pod2usage(-exitstatus => 0, -verbose => 2) if $man;

openlog('bruker-setup', 'nofatal,pid', 'user') if $syslog;

###
# Some info about myself
my @Version =  split(' ','$Revision: 1.1 $ ');
my $Version = $Version[1];
print "$program (Version $Version)\nCopyright (c) 2014 Bruker BioSpin GmbH\n" if $verbose;

###
# default file names
my $lshw	= '/usr/sbin/lshw';
my $netcfg	= '/etc/sysconfig/network-scripts/ifcfg';

my $OS_Version = get_os_version();
print "OS_Version = $OS_Version\n" if $verbose;

####
# Now get MAC addresses and PCI Bus info of Ethernet Cards
####
my %mac;
my %productName;
my $logicalname;
my @lines;
###
# Call lshw with NETWORK Class option to fetch MAC info
###

die "Missing $lshw\n" unless -x $lshw;

syslog(LOG_INFO, "Reading network configuration with lshw") if $syslog;
$/ = '*-network';
open(LSHW,"$lshw -quiet -class network|") || die "can't pipe to $lshw: $!\n";
while (<LSHW>)
{
    chomp;
    $logicalname = "";   
    @lines = split("\n",$_);
    foreach my $line (@lines) {
	if ( /logical name:\s([\w\d]*)/ ) {
	  $logicalname = $1;
	  next:
	}
	if (/serial:\s([0-9A-Fa-f:]+)/ && $logicalname ne "") {
	  $mac{$logicalname} = $1;
	}
	if (/product:\s(.*)/ && $logicalname ne "") {
	  $productName{$logicalname} = $1;
	  last;
	}
    }
}
close(LSHW);
$/ = "\n";

ShowHashArray"MAC:",(%mac) if $verbose;

###
# Set MAC Address for the device, which is not eno1
###
if (scalar keys %mac != 2) {
	my $msg= "A z440 Workstation should only have 2 network devices, but ". scalar keys(%mac) . " devices were found.";
	print $msg."\n" if $verbose;
	syslog(LOG_INFO, $msg) if $syslog;
}
# There should only be two network devices eno1 and another one
if (exists $mac{'eno1'}) {
	delete($mac{'eno1'});
} else {
	my $msg = "$program aborted: Ethernet device eno1 does not exist, but should be present!";
	print $msg."\n" if $verbose;
	syslog(LOG_ERR, $msg) if $syslog;
	closelog  if $syslog;
	exit 0;
}
# Set only for the first device found
foreach my $dev (keys %mac) {
	if($dev !~ /^enp.s./ ) {
	    my $msg = "Ethernet device $dev has a different name as expected (enpXsX).";
	    print $msg."\n" if $verbose;
	    syslog(LOG_INFO, $msg) if $syslog;
	}
	setMacAdress($mac{$dev},$productName{$dev});
	last;
}

closelog  if $syslog;

exit;

###################
##               ##
##  Subroutines  ##
##               ##
###################
sub setMacAdress($$) {
    
    my ($address, $product) = @_;
    chomp($address);
    chomp($product);
    my $uuid = `uuidgen`;
    chomp($uuid); 
    
    my $now = ctime();
    my $created = "Created by $program $now";
    my $msg = "Write network device config file $netcfg-ens1";
    print $msg."\n" if $verbose;
    syslog(LOG_INFO, $msg) if $syslog;
    
    open(IFCFG, ">$netcfg-ens1" ) or die "Cannot open $netcfg-ehs1: $!";
    print IFCFG "# ", $product,"\n";
    print IFCFG "# $created\n";
    print IFCFG 'TYPE="Ethernet"',"\n";
    print IFCFG 'BOOTPROTO="dhcp"',"\n";
    print IFCFG 'DEFROUTE="yes"',"\n";
    print IFCFG 'IPV4_FAILURE_FATAL="no"',"\n";
    print IFCFG 'IPV6INIT="no"',"\n";
    print IFCFG 'IPV6_AUTOCONF="yes"',"\n";
    print IFCFG 'IPV6_DEFROUTE="yes"',"\n";
    print IFCFG 'IPV6_FAILURE_FATAL="no"',"\n";
    print IFCFG 'NAME="External Network"',"\n";
    print IFCFG 'ONBOOT="yes"',"\n";
    print IFCFG 'IPV6_PEERDNS="yes"',"\n";
    print IFCFG 'IPV6_PEERROUTES="yes"',"\n";
    print IFCFG 'IPV6_PRIVACY="no"',"\n";
    print IFCFG 'DEVICE="ens1"',"\n";
    print IFCFG 'UUID="',$uuid,'"',"\n";
    print IFCFG 'HWADDR="',$address,'"',"\n";
    close(IFCFG);
}

sub get_os_version()
{
    my $querycmd = 'rpm -qf --queryformat %{Name} /etc/redhat-release';
    my $redhat = `$querycmd`;
    
    chomp $redhat;
    $querycmd = 'rpm -q --queryformat %{version} ' . $redhat;
    
    my $redhat_release = `$querycmd`;
    
    my $rh_release = (int $redhat_release);
    return $rh_release;
}

sub ShowHashArray($%)
{
    my $head = shift;
    my %hash = @ARG;
    print "$head:\n";
    while (my($key,$val) = each(%hash))
    {
	print " $key => $val\n";
    }
}

__END__

=head1 NAME

assign-default-networks - Write ifcfg-ens1 file and add the MAC and UUID of the second non mainboard network device

=head1 SYNOPSIS

assign-default-networks [options]

Options:

     -help            brief help message
     -man             prints the manual page
     -verbose         create verbose output

=head1 OPTIONS

=over 8

=item B<-help>

    Print a brief help message and exits.

=item B<-man>

    Prints the manual page and exits.


=item B<-verbose>

    Print additional debug information

=back


=head1 DESCRIPTION

This script is required during system boot by the service bruker-setup
to assing the MAC addresse in ifcfg-ens1. It assumes that eno1 device is used on the motherboard, which 
should be connected to the spectrometer. The other device is therfore set to ens1.

=cut

