Last active
October 8, 2020 19:55
-
-
Save caseyrichins/bb4f93d37cc6bff90b3961ca2f52623f to your computer and use it in GitHub Desktop.
create_multipath.pl - Essentially this script takes the the iscsi target information and creates and friendly name multipath.conf configuration based upon the iscsi volume name.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl -w | |
# This is not my script, it is one that I've used for a very long time but don't | |
# know whom the original author is. Essentally this script takes the the iscsi | |
# target information and creates and friendly name multipath.conf configuration | |
# based upon the iscsi volume name. It takes the end string of iscsi target after | |
# the last "-" to create a frendly dev mapper path. I would like to simplify it | |
# and re-write it in python but but I haven't had the time to do so and my perl | |
# skill are limited, so the perl version is maitained with what little changes | |
# I've made and what limited knowledge of perl I have. | |
# | |
# To use the script you simply login your iscsi target volumes and execute the | |
# script, if the config passed validation it is copied to /etc/multipath.conf | |
# afterwhich you need to either restart multipathd service or refresh multipath | |
# configuration with 'multipath -r'. Make sure you have perl libary | |
# perl-Data-Dump installed or it will fail to work. | |
# | |
# Improvements and requests for simplfication are encouraged. | |
# | |
# Last known modification: October 8, 2020 | |
use strict; | |
use Data::Dumper; | |
my $disk_map = {}; | |
my $last = {}; | |
my $customer_map = {}; | |
my @tmp = (); | |
my $cmd = "iscsiadm -m session -P 3"; | |
my $customer; | |
if ($ARGV[0]) { | |
print "Setting \$customer to $ARGV[0]\n"; | |
$customer = sprintf("%06d", $ARGV[0]); | |
} | |
my $PID=$$; | |
my $old_PID=''; | |
open ( RESULT, ">", "/tmp/multipath.$PID" ) | |
or die "Cannot open /tmp/multipath.$PID\n"; | |
sub check_pid() | |
{ | |
open ( PIDFILE, "+<", "/var/run/create_multipath") | |
or die "Cannot open /var/run/create_multipath\n"; | |
while (<PIDFILE>) | |
{ | |
if ( $_ ) | |
{ | |
my $proc=$_; | |
if ( -d "/proc/$proc" ) | |
{ | |
close PIDFILE; | |
return 1; | |
} | |
else | |
{ | |
close PIDFILE; | |
return 0; | |
} | |
} | |
} | |
} | |
if ( ! -f "/var/run/create_multipath") | |
{ | |
open ( PIDFILE, ">", "/var/run/create_multipath") | |
or die "Cannot open /var/run/create_multipath\n"; | |
close PIDFILE; | |
} | |
while ( check_pid ) | |
{ | |
print "$PID sleeping 5\n"; | |
sleep 5; | |
} | |
open ( PIDFILE, ">", "/var/run/create_multipath") | |
or die "Cannot open /var/run/create_multipath\n"; | |
print PIDFILE $PID; | |
close PIDFILE; | |
print "$PID Its me!\n"; | |
# print multipath.conf headers | |
print RESULT "# | |
defaults { | |
user_friendly_names yes | |
polling_interval 10 | |
path_selector \"round-robin 0\" | |
path_grouping_policy multibus | |
path_checker tur | |
rr_min_io_rq 10 | |
max_fds 8192 | |
rr_weight priorities | |
failback immediate | |
features 0 | |
no_path_retry queue | |
} | |
multipaths {\n"; | |
my $good; | |
do { | |
# If I'm not specifically adding a Customer's Volume, assume the result is good | |
if (! defined $customer ) { | |
$good = 1; | |
} | |
else | |
{ | |
$good = 0; | |
} | |
print "Running $cmd\n"; | |
open ISCSI, "$cmd |"; | |
while (<ISCSI>) | |
{ | |
#Target: iqn.2001-05.com.equallogic:0-8a0906-80995e803-c8b0000009e4b71b-kvmt43 | |
# Attached scsi disk sdjg State: running | |
# Attached scsi disk sdjj State: running | |
if ($_ =~ m/^Target:\s+(\S+)/) | |
{ | |
$last->{'target'} = $1; | |
@tmp = split("-",$last->{'target'}); | |
$last->{'customerID'} = @tmp[@tmp - 1]; | |
print "Found volume for $last->{'customerID'}\n"; | |
} | |
if ($_ =~ m/^\s+Attached scsi disk (\S+)/) | |
{ | |
$disk_map->{$1}->{'Target'} = $last->{'target'}; | |
$disk_map->{$1}->{'customerID'} = $last->{'customerID'}; | |
print "$1 = $disk_map->{$1}->{'customerID'} = $disk_map->{$1}->{'Target'}\n"; | |
$good = 1 if (defined $customer && $last->{'customerID'} == $customer); | |
} | |
} | |
close ISCSI; | |
print "Could not find volume for account $customer\n" if ($good == 0 && defined $customer); | |
sleep 1 if ($good == 0); | |
} until ($good == 1); | |
do { | |
if (defined $customer) { | |
$good = 0; | |
} | |
else | |
{ | |
$good = 1; | |
} | |
print "Running multipath -l\n"; | |
open MULTIPATH, "multipath -l |"; | |
while (<MULTIPATH>) | |
{ | |
#eq-057 (36090a038805e097b1bb7f40200007097) dm-162 EQLOGIC,100E-00 | |
#[size=30G][features=0][hwhandler=0][rw] | |
#\_ round-robin 0 [prio=0][active] | |
# \_ 848:0:0:0 sdjc 8:352 [active][undef] | |
if ($_ =~ m/\(([^\)]+)\)/) | |
{ | |
$last->{'WWID'} = $1; | |
} | |
if ($_ =~ m/\d+:\d+:\d+:\d+\s+(\S+)/) | |
{ | |
$disk_map->{$1}->{'WWID'} = $last->{'WWID'}; | |
print "$1 = $disk_map->{$1}->{'WWID'}\n"; | |
$good = 1; | |
} | |
} | |
close MULTIPATH; | |
#print Dumper($disk_map); | |
for my $disk (keys %$disk_map) | |
{ | |
#$customer_map->{$disk_map->{$disk}->{'customerID'}}->{'customerID'} = $disk_map->{$disk}->{'customerID'}; | |
if (! defined $disk_map->{$disk}->{'WWID'} || $disk_map->{$disk}->{'WWID'} =~ m/^$/) { | |
print "\$disk_map->{\$disk}->{'WWID'} ($disk) Is not defined\n"; | |
} | |
$customer_map->{$disk_map->{$disk}->{'customerID'}}->{'WWID'} = $disk_map->{$disk}->{'WWID'}; | |
$customer_map->{$disk_map->{$disk}->{'customerID'}}->{'Target'} = $disk_map->{$disk}->{'Target'}; | |
} | |
for my $customerID (sort keys %$customer_map) | |
{ | |
if (! defined $customer_map->{$customerID}->{'WWID'}) { | |
print STDERR "Missing CustomerID->WWID relationship. Trying again\n"; | |
sleep 1; | |
$good=0; | |
} | |
else | |
{ | |
print RESULT "\tmultipath { | |
\t\twwid\t\t$customer_map->{$customerID}->{'WWID'} | |
\t\tfailback\t\timmediate | |
\t\trr_min_io\t\t1000 | |
\t\talias\t\t\t$customerID | |
\t} | |
"; | |
} | |
} | |
print "Something went wrong with multipath -l output." if (! $good); | |
sleep 1 if (! $good); | |
} until ($good); | |
# print closing curly | |
print RESULT "}\n"; | |
close RESULT; | |
`cp /tmp/multipath.$PID /etc/multipath.conf`; | |
unlink "/tmp/multipath.$PID"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment