Skip to content

Instantly share code, notes, and snippets.

@caseyrichins
Last active October 8, 2020 19:55
Show Gist options
  • Save caseyrichins/bb4f93d37cc6bff90b3961ca2f52623f to your computer and use it in GitHub Desktop.
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.
#!/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