Skip to content

Commit

Permalink
mxnetctl: initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
donald committed Jun 18, 2016
1 parent 6c051bf commit 3eb92c4
Showing 1 changed file with 254 additions and 0 deletions.
254 changes: 254 additions & 0 deletions mxnetctl/mxnetctl
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
#! /usr/bin/perl
use strict;
use warnings;

use Getopt::Long;

# options

our ($opt_quiet,$opt_noop,$opt_ignore_hw);
use constant OPTIONS => (
'quiet' => \$opt_quiet,
'noop' => \$opt_noop,
);

sub USAGE {
return <<"__EOF__";
usage: $0
start [options]
stop [options] # (ignored)
upgrade # switch from eth to net
options:
--quiet : do not log actions
--noop : dry run
__EOF__
}

sub scandir {
my ($dirname)=@_;
opendir my $dir,$dirname or die "$dirname: $!\n";
return sort grep !/^\./,readdir $dir;
}

sub slurpfile {
my ($path)=@_;
open my $fh,'<',$path or die "$path: $!\n";
return join ('',<$fh>);
}

sub slurpfile_chomp {
my $data=slurpfile($_[0]);
chomp($data);
return $data;
}

sub network_devices { # -> ( 'bond0','dummy0','eth0','eth1','eth2','eth2.43','eth3','eth4','eth5','lo','sit0' )
return grep -d "/sys/class/net/$_",scandir('/sys/class/net');
}

sub network_hardware_devices { # -> ( eth0','eth1','eth2','eth3','eth4','eth5' )
return grep -e "/sys/class/net/$_/device",network_devices();
}


sub get_hw_address { # 'eth1' -> '00:1b:21:79:76:67'
my ($dev)=@_;
my $path="/sys/class/net/$dev/address";
return slurpfile_chomp($path);
}


our %HW_TO_DEV; # ( '00:1b:21:79:76:67' => 'net02' , ... )
our %DEV_TO_HW; # ('net02'=>'00:1b:21:79:76:67', ... )
our $CHANGES;


sub register_stable {
my ($hw,$dev)=@_;

# force one-to-one mapping, even if file is erroneus

exists $DEV_TO_HW{$dev} and delete $HW_TO_DEV{$DEV_TO_HW{$dev}};
exists $HW_TO_DEV{$dev} and delete $DEV_TO_HW{$HW_TO_DEV{$hw}};


$HW_TO_DEV{$hw}=$dev;
$DEV_TO_HW{$dev}=$hw;
$CHANGES++;
}


sub read_mxnet {
%HW_TO_DEV=();
%DEV_TO_HW=();
-r '/etc/local/mxnet' or return;
open my $file,'<','/etc/local/mxnet' or die "/etc/local/mxnet: $!\n";
while (<$file>) {
s/#.*//;
/\S/ or next;
my ($hw,$dev)=split;
register_stable($hw,$dev);
}
$CHANGES=0;
}

sub write_mxnet {
my $mxnet;
unless ($opt_noop) {
open my $mxnet,'>',"/etc/local/mxnet" or die "/etc/local/mxnet: $!\n";
print $mxnet "# generated ".scalar(localtime)." by $0\n\n";
for my $dev (sort keys %DEV_TO_HW) {
print $mxnet $DEV_TO_HW{$dev},' ',$dev."\n";
}
print $mxnet "\n";

# open my $out,'>',"/etc/local/mxnet-udev.rules" or die "/etc/local/mxnet-udev.rules: $!\n";
# print $out "# generated ".scalar(localtime)." by $0\n\n";
# for my $dev (sort keys %DEV_TO_HW) {
# print $out qq'SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="$DEV_TO_HW{$dev}", NAME="$dev"\n';
# }
}
}

sub get_unused_name {
my $next_name=0;
while(1) {
my $name=sprintf 'net%02d',$next_name++;
exists $DEV_TO_HW{$name} or return $name;
}
}


sub rename_if {
my ($src,$dst)=@_;
warn "rename $src to $dst\n" unless $opt_quiet;
unless ($opt_noop) {
if (defined $src =~ /^eth/) {
system 'ip','link','set',$src,'name',$dst,'alias',$src; # continue on error
$? and warn "failed to rename $src to $dst\n";
} else {
system 'ip','link','set',$src,'name',$dst; # continue on error
$? and warn "failed to rename $src to $dst\n";
}
}
}


sub preferred_device_name {
my ($dev,$hw)=@_;

exists $HW_TO_DEV{$hw} and return $HW_TO_DEV{$hw}; # configured
$dev =~ /(\d+)/;

my $new_dev=sprintf 'net%02d',$1; # stable number if free
unless (exists $DEV_TO_HW{$new_dev}) {
register_stable($hw,$new_dev);
return $new_dev;
}

$new_dev=get_unused_name(); # any free new number
register_stable($hw,$new_dev);
return $new_dev;
}



our $TMP_NUM=0;
sub out_of_the_way {
my ($dev)=@_; # only 'netXX' or 'ethX' - never 'tmpXX'

-e "/sys/class/net/$dev/device" or return;

my $i = $dev=~/(\d+)/;
rename_if($dev,sprintf('tmpnet%02d',$TMP_NUM++));
}

sub start {
read_mxnet();

# 1: rename configured ethX and netXX devices to configured netXX - move away conflicting devices

for my $dev (grep /^(eth|net)(\d+)/,network_hardware_devices()) {
my $hw=get_hw_address($dev);
my $new_dev=preferred_device_name($dev,$hw);
if ($dev ne $new_dev) {
out_of_the_way($new_dev);
rename_if($dev,$new_dev);
}
}

# 2 : rename moved away devices to netXX

for my $dev (grep /^(tmpnet)(\d+)/,network_hardware_devices()) {
my $hw=get_hw_address($dev);
my $new_dev=preferred_device_name($dev,$hw);
rename_if($dev,$new_dev);
}

#if ($CHANGES || ! -e "/etc/local/mxnet-udev.rules") {
if ($CHANGES) {
write_mxnet();
}
}



sub upgrade {
umask 022;

-d '/etc/local' or mkdir '/etc/local' or die "/etc/local: $!\n";

read_mxnet();
for my $dev (grep /^(eth|net)(\d+)/,network_hardware_devices()) {
my $hw=get_hw_address($dev);
my $new_dev=preferred_device_name($dev,$hw);
}
write_mxnet();

unlink "/etc/udev/rules.d/70-persistent-net.rules";

my $data=slurpfile('/etc/systemd/system/network.service');
unless ($data=~/mxnetctl/) {
$data=~s#^ExecStart#ExecStart=/usr/sbin/mxnetctl start\nExecStart#m;
$data=~s/eth(\d+)/sprintf 'net%02d',$1/eg;
open my $out,'>','/etc/systemd/system/network.service' or die "/etc/systemd/system/network.service: $!\n";
print $out $data;
close $out;
}

warn "updated /etc/local/mxnet , /etc/systemd/system/network.service , /etc/udev/rules.d/70-persistent-net.rules - reboot to activate\n";
}







GetOptions(OPTIONS) or die USAGE;

@ARGV>=1 or die USAGE;

my ($cmd)=@ARGV;


if ($cmd eq 'start') {
start();
} elsif ($cmd eq 'stop') {
;
} elsif ($cmd eq 'upgrade') {
upgrade();
;
} else {
die USAGE;
}








0 comments on commit 3eb92c4

Please sign in to comment.