#!/usr/bin/python3
import subprocess
import os

class SilentException(Exception):
    pass

class DiskInfo(object):
    def __init__(self, devname, devinfo):
        self.name = devname
        self.path = '/dev/' + devname
        self.wwn = None
        self.model = devinfo.get('model', 'Unknown')
        self.driver = devinfo.get('adapter_driver', 'Unknown')
        self.size = devinfo.get('size', 0)  # in MiB
        if not devinfo.get('is_local', False):
            raise SilentException("Not local")
        if devinfo.get('is_removable', False):
            raise SilentException("Removable")
        if devinfo.get('is_usb', False):
            raise SilentException("USB device")
        if devinfo.get('type', '').lower() in ('cd-rom',):
            raise SilentException("CD-ROM device")
        if self.size < 2048:
            raise SilentException("Too small")

        


    @property
    def priority(self):
        if self.model.lower() in ('m.2 nvme 2-bay raid kit', 'thinksystem_m.2_vd', 'thinksystem m.2', 'thinksystem_m.2'):
            return 0
        if self.driver == 'vmw_ahci':
            return 2
        if self.driver == 'nvme_pcie':
            return 3
        return 99

    def __repr__(self):
        return repr({
            'name': self.name,
            'path': self.path,
            'wwn': self.wwn,
            'driver': self.driver,
            'size': self.size,
            'model': self.model,
        })

def list_disks():
    current_dev = None
    disks = {}
    devlist = subprocess.check_output(['localcli', 'storage', 'core', 'device', 'list'])
    if not isinstance(devlist, str):
        devlist = devlist.decode('utf8')
    devbyadp = {}
    for line in devlist.split('\n'):
        if not line.strip():
            continue
        if not line.startswith(' '):
            current_dev = line.rsplit(':', 1)[0]
            if current_dev not in disks:
                disks[current_dev] = {}
        elif current_dev:
            if '   Model:' in line:
                disks[current_dev]['model'] = ' '.join(line.split()[1:])
            elif '   Driver:' in line:
                disks[current_dev]['driver'] = ' '.join(line.split()[1:])
            elif '   Is Local:' in line:
                disks[current_dev]['is_local'] = ' '.join(line.split()[2:]).lower() == 'true'
            elif '   Is Removable:' in line:
                disks[current_dev]['is_removable'] = ' '.join(line.split()[2:]).lower() == 'true'
            elif '   Size:' in line:  # in MiB
                disks[current_dev]['size'] = int(line.split()[1])
            elif '   Is SSD:' in line:
                disks[current_dev]['is_ssd'] = ' '.join(line.split()[2:]).lower() == 'true'
            elif '   Is USB:' in line:
                disks[current_dev]['is_usb'] = ' '.join(line.split()[2:]).lower() == 'true'
            elif '   Is Removable:' in line:
                disks[current_dev]['is_removable'] = ' '.join(line.split()[2:]).lower() == 'true'
            elif 'Device Type:' in line:
                disks[current_dev]['type'] = ' '.join(line.split()[2:])
    for dev in disks:
        pathlist = subprocess.check_output(['localcli', 'storage', 'core', 'path', 'list', '--device', dev])
        if not isinstance(pathlist, str):
            pathlist = pathlist.decode('utf8')
        for line in pathlist.split('\n'):
            if not line.strip():
                continue
            if not line.startswith(' '):
                continue
            if '   Adapter Identifier:' in line:
                adpname = ' '.join(line.split()[2:])
                disks[dev]['adapter_id'] = adpname
            elif '   Adapter:' in line:
                adp = ' '.join(line.split()[1:])
                disks[dev]['adapter'] = adp
                devbyadp.setdefault(adp, []).append(dev)
    adapterlist = subprocess.check_output(['localcli', 'storage', 'core', 'adapter', 'list'])
    if not isinstance(adapterlist, str):
        adapterlist = adapterlist.decode('utf8')
    driverbyadp = {}
    linenum = 0
    for line in adapterlist.split('\n'):
        linenum += 1
        if not line.strip():
            continue
        if linenum < 3:
            continue
        parts = line.split()
        if len(parts) < 2:
            continue
        adp = parts[0]
        driver = parts[1]
        driverbyadp[adp] = driver
    for adp in devbyadp:
        driver = driverbyadp.get(adp, 'Unknown')
        for dev in devbyadp[adp]:
            disks[dev]['adapter_driver'] = driver
    return disks
        
def main():
    disks = []
    try:
        alldisks = list_disks()
    except Exception as e:
        print("Error listing disks: {0}".format(str(e)))
        alldisks = {}
    for disk in alldisks:
        try:
            disks.append(DiskInfo(disk, alldisks[disk]))
        except SilentException:
            pass
        except Exception as e:
            print("Skipping {0}: {1}".format(disk, str(e)))
    nd = [x.name for x in sorted(disks, key=lambda x: [x.priority, x.size])]
    if nd:
        with open('/tmp/storagecfg', 'w') as sc:
            sc.write(f'clearpart --all --drives={nd[0]} --overwritevmfs\n')
            sc.write(f'install --drive={nd[0]} --overwritevmfs\n')
    else:
        with open('/tmp/storagecfg', 'w') as sc:
            sc.write(f'clearpart --firstdisk --overwritevmfs\n')
            sc.write(f'install --firstdisk --overwritevmfs\n')


if __name__ == '__main__':
    main()
