mpath2multipath
Automatically give names to mpaths.
Size 6.8 kB - File type text/python-sourceFile contents
#!/usr/bin/python
"""mpath2multipath [wwwn=Alias]* [DefaultAlias]
This program generates an output to be passed to the multipath configuration file.
Every storagesystem gets an Alias in the following order.
If an alias is found for the wwwn of the storagesystem it is taken.
If there is no alias found for the wwwn the DefaultAlias is used.
If no default alias is given the wwwn is the alias.
"""
__version__="$Revision: 1.2 $"
# $Id: mpath2multipath.py,v 1.2 2008/03/19 13:49:59 marc Exp $
import re
import popen2
import sys
import os.path
import commands
class DiskDescriptor(object):
def getDescriptor(self, **kwds):
return 0
class _DefaultDiskDescriptor(DiskDescriptor):
def getDescriptor(self, **kwds):
return int(kwds["lun"])
DefaultDiskDescriptor=_DefaultDiskDescriptor()
class _XPDiskDescriptor(DiskDescriptor):
SCSI_INFO_CMD="scsi_info"
DESC_DIGITS=-5
DESC_KEY="LUN"
def getDescriptor(self, **kwds):
if kwds.has_key("digits"):
self.DESC_DIGITS=-kwds["digits"]
__cmd="%s %s" %(self.SCSI_INFO_CMD,kwds["device"])
(_rc, output)=commands.getstatusoutput(__cmd)
if _rc >> 8 != 0:
raise OSError(_rc >> 8, output)
_pairs=output.split(":")
_descriptors=dict()
# print _pairs
for _pair in _pairs:
if _pair.find("=")<1:
pass
# print _pair
(_key, _value)=_pair.split("=")
_descriptors[_key]=_value[1:-1]
# last 4 digits
return int(_descriptors[self.DESC_KEY][self.DESC_DIGITS:], 16)
XPDiskDescriptor=_XPDiskDescriptor()
def getWWWN(scsi_hostid, scsi_busid, scsi_id):
# print "%s, %s, %s" %(scsi_hostid, scsi_busid, scsi_id)
filename="/sys/class/fc_transport/target%s:%s:%s/node_name" %(scsi_hostid, scsi_busid, scsi_id)
if not os.path.exists(filename):
return ""
nodenamef=open(filename, "r")
nodename=nodenamef.readlines()[0]
nodename=nodename[2:-1]
nodenamef.close()
return nodename
def printMultipathConf(scsi_devs, padding=3):
_wwwns=scsi_devs.keys()
_wwwns.sort()
for wwwn in _wwwns:
_luns=scsi_devs[wwwn].keys()
_luns.sort(lambda x, y: int(x)-int(y))
for lun in _luns:
format="""multipath {
wwid %s
alias %s_%0"""+str(padding)+"""u
}"""
print format %(scsi_devs[wwwn][lun], wwwn, lun)
def main():
from optparse import OptionParser
parser = OptionParser(description=__doc__, version=__version__)
parser.add_option("-X", "--xp", dest="xp", default=False, action="store_true", help="Behave as all attached devices are HP XPs.")
parser.add_option("-F", "--full", dest="full", default=False, action="store_true", help="Reformat all multipath devices independent on name.")
parser.add_option("-W", "--xpwwwn", dest="xpwwwn", action="append", type="string", help="Define the wwns to be handled as HP XP. Implies --xp.")
parser.add_option("" , "--infile", dest="infile", default="", action="store", type="string", help="Instead of executing multipath use this file as input")
parser.add_option("-P", "--padding", dest="padding", default=3, action="store", type="int", help="Padding for the lower part of the description. Defaults to 3 digits.")
parser.add_option("", "--devname", dest="devname", default="mpath\d+",action="store", type="string", help="Device regular expression to match. Defaults to mpath")
(options, args) = parser.parse_args()
DEFAULT_KEY="__DEFAULT__"
scsi_devs=dict()
mappings=dict()
for arg in args:
if arg.find("=")>0:
(key, value)=arg.split("=")
else:
value=arg
key=DEFAULT_KEY
mappings[key]=value
if arg=='-h' or arg=='--help':
usage(sys.argv[0])
sys.exit(0)
descriptors=dict()
if options.full:
options.devname="\S+"
if options.xp and not options.xpwwwn:
descriptors[DEFAULT_KEY]=XPDiskDescriptor
elif options.xpwwwn:
for _xpwwwn in options.xpwwwn:
descriptors[_xpwwwn]=XPDiskDescriptor
else:
descriptors[DEFAULT_KEY]=DefaultDiskDescriptor
if options.infile:
_lines=open(options.infile)
else:
__cmd="multipath -l"
child=popen2.Popen3(__cmd, False)
_lines=child.fromchild.readlines()
# __rc=child.wait()
# if __rc==0:
id=None
for line in _lines:
regexp=re.match("^(?P<device>%s)\s+\((?P<uid>[0-9a-fA-F]+)\)" %options.devname, line)
if regexp:
id=regexp.group("uid")
device=regexp.group("device")
# print id
# print device
if not regexp:
regexp=re.match("^(?P<device>\S+)\s+\((?P<uid>[0-9a-fA-F]+)\)", line)
if regexp:
id=None
regexp=re.match("^.+([0-9]+):([0-9]+):([0-9]+):([0-9]+)", line)
if id and regexp:
# print id, regexp
(scsi_hostid, scsi_busid, scsi_id, scsi_lun)=regexp.groups()
wwwn=getWWWN(scsi_hostid, scsi_busid, scsi_id)
# print wwwn
if mappings.has_key(wwwn):
key=mappings[wwwn]
elif mappings.has_key(DEFAULT_KEY):
key=mappings[DEFAULT_KEY]
else:
key=wwwn
if descriptors.has_key(wwwn):
descriptor=descriptors[wwwn]
elif descriptors.has_key(DEFAULT_KEY):
descriptor=descriptors[DEFAULT_KEY]
else:
descriptor=DefaultDiskDescriptor
if not scsi_devs.has_key(key):
scsi_devs[key]=dict()
disk_descriptor=descriptor.getDescriptor(wwwn=wwwn, lun=scsi_lun, id=scsi_id, uid=id, device=os.path.join("/dev/mapper", device), digits=options.padding)
scsi_devs[key][disk_descriptor]=id
printMultipathConf(scsi_devs, options.padding)
if __name__ == "__main__":
main()
#/^mpath.*/ {
# match($2, /\((.*)\)/, _id)
# mpath=$1; id=_id[1];
# scsi_hostid=[]
# scsi_busid=[]
# scsi_id=[]
# scsi_lun=[]
#}
#/[0-9]+:[0-9]+:[0-9]+:[0-9]+/ {
# match($2, /([0-9]+):([0-9]+):([0-9]+):([0-9]+)/, scsi_addr);
# scsi_hostid=(scsi_hostid<scsi_addr[1])?scsi_addr[1]:scsi_hostid
# scsi_busid=(scsi_busid<scsi_addr[2])?scsi_addr[2]:scsi_busid
# scsi_id=(scsi_id<scsi_addr[3])?scsi_addr[3]:scsi_id
# scsi_lun=(scsi_lun<scsi_addr[4])?scsi_addr[4]:scsi_lun
#}
#$0=="" && scsi_hostid >=0 && scsi_busid >= 0 && scsi_id >= 0 && scsi_lun >= 0 {
# print "multipath {"
# print " wwid "id
# print " alias "storagename"_"scsi_lun
# print "}"
################
# $Log: mpath2multipath.py,v $
# Revision 1.2 2008/03/19 13:49:59 marc
# - added xp compatibility mode
# - more configurable
#
# Revision 1.1 2007/09/17 11:38:04 marc
# - new release 0.1-9
#
Click here to get the file