#!/usr/bin/env python """ Mark6 utility m6sg_mount v2.0 Usage: m6sg_mount [-u] With the '-u' option all scatter-gather disks are unmounted. With no options specified, all "diskpack" disks are mounted. The main purpose of this script is to avoid having to start cplane, then dplane, and then send the necessary da-client commands. """ import pyudev, re, subprocess, sys MARK6_ROOT = '/mnt/disks/%d/%d' MARK6_META = '/mnt/disks/.meta/%d/%d' CHECK_RESULTS = False # specifies whether to check results from subprocess() launches # Changelog: # xx/2015 v1.0 Jan Wagner, basic version for quick (un)mounting # xx/2015 v1.1 Harro Verkouter, improvements to preseve consistent mount points # 11/2015 v2.0 Jan Wagner, updated to use pyudev instead of 3rd party 'lsscsi' def list_MPT2SAS_disks(): list = [] context = pyudev.Context() ctrl_ids = [] # Find controllers with disks (perhaps unpartitioned) for dev in context.list_devices(subsystem='block', DEVTYPE='disk'): pdev = dev.find_parent('pci') if (pdev == None): continue if (pdev.driver == 'mpt2sas'): # DEVPATH /sys/devices/pci0000:00/0000:00:02.0/0000:06:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/block/sdb # Controllers may have target0:0:0, target1:0:0, target17:0:0, ... depending perhaps on PCIe slot (0, 1, 17, ...) # Since target numbers n are not known in advance we don't use , but replace it with an index (0,1,2,...) dp = dev['DEVPATH'] h = int(re.search('\/host([0-9]*)\/',dp).group(1)) if h not in ctrl_ids: ctrl_ids.append(h) ctrl_ids.sort() # Now find partitions on disks behind controllers for dev in context.list_devices(subsystem='block', DEVTYPE='partition'): pdev = dev.find_parent('pci') if (pdev.driver == 'mpt2sas'): entry = {} entry['devnode'] = dev.device_node entry['fs'] = dev.get('ID_FS_TYPE') entry['diskmodel'] = dev.get('ID_MODEL') entry['diskserial'] = dev.get('ID_SERIAL') # Determine which "slot" (module) and "disk" the SAS target belongs to # E.g., DEVPATH /devices/pci0000:00/0000:00:02.0/0000:06:00.0/host0/port-0:15/end_device-0:15/target0:0:15/0:0:15:0/block/sdq/sdq1 # has 'target0:0:15' on 'host0' which means target 15 (0..15) which maps to module 2 (1..4), slot 7 (0..7) # - no SAS Expanders are assumed to be in use, and at most 16 SAS targets per controller # - SAS targets 0-7 on controller 0 are in "module 1" in "slots 0-7" # - SAS targets 8-15 on controller 0 are in "module 2" in "slots 0-7" # - SAS targets 0-7 on controller 1 are in "module 3" in "slots 0-7" # - SAS targets 8-15 on controller 1 are in "module 4" in "slots 0-7" dp = dev['DEVPATH'] h = int(re.search('\/host([0-9]*)\/',dp).group(1)) m = ctrl_ids.index(h) t = re.search('\/target([0-9]*:[0-9]*:[0-9]*)\/',dp).group(1) t = [int(x) for x in t.split(':')] if (t[-1] > 15): # print ('Unexpected target nr %d not in range of 0-15!' % (t[-1])) t[-1] = int(t[-1]) % 16 entry['mk6_module'] = (1 + t[-1]/8) + 2*m # 1-based count entry['mk6_slot'] = t[-1] % 8 # 0-based count if dp[-1]=='1': entry['mk6_mountpoint'] = MARK6_ROOT % (entry['mk6_module'],entry['mk6_slot']) elif dp[-1]=='2': entry['mk6_mountpoint'] = MARK6_META % (entry['mk6_module'],entry['mk6_slot']) else: entry['mk6_mountpoint'] = None #print dp,h,m,t,dp[-1],entry['mk6_module'],entry['mk6_slot'],entry['mk6_mountpoint'] list.append(entry) list = sorted(list, key=lambda k: k['mk6_mountpoint']) return list def mount(dev,dir): print ('Mounting %s to %s' % (dev,dir)) p = [] p.append( subprocess.Popen(["/usr/bin/sudo", "/bin/mount", dev, dir], stdout=subprocess.PIPE, stderr=subprocess.PIPE) ) p.append( subprocess.Popen(["/usr/bin/sudo", "/bin/chmod", "775", dir], stdout=subprocess.PIPE, stderr=subprocess.PIPE) ) p.append( subprocess.Popen(["/usr/bin/sudo", "/bin/chown", "oper:mark6", dir], stdout=subprocess.PIPE, stderr=subprocess.PIPE) ) return p def unmount(dir): print ('Unmounting %s' % (dir)) p = subprocess.Popen(["/usr/bin/sudo", "/bin/umount", dir], stdout=subprocess.PIPE, stderr=subprocess.PIPE) return [p] def mount_all(): procs = [] for entry in list_MPT2SAS_disks(): procs = procs + mount(entry['devnode'], entry['mk6_mountpoint']) return procs def unmount_all(): procs = [] for entry in list_MPT2SAS_disks(): procs = procs + unmount(entry['mk6_mountpoint']) return procs def main(argv=sys.argv): if (not(len(argv) in [1,2]) or (len(argv)==2 and argv[1]!='-u')): print __doc__ sys.exit(-1) if (len(argv)==2 and argv[1]=='-u'): procs = unmount_all() else: procs = mount_all() if CHECK_RESULTS: for p in procs: (o,rc) = p.communicate() if (len(rc)>0): print rc if __name__ == "__main__": main(sys.argv)