#!/usr/bin/python

import os
import re
import subprocess
import sys
import time
import getopt
import isi.misc

def usage():
    print >> sys.stderr, '''\
    usage: isi_jlog -f -d devname
    -f: force create journallog partition, even if one exists already
    -d devname: drive to use
    -s : disable journal logging
    If the disk is in use by ufs mounts, it cannot be used for jlog.
    This implies using an unused drive for imdd
    example: isi_jlog -d /dev/da3
    '''

def gpart_drive_format(dev, force):

    import isi.sys.disk as disk
    import isi.sys.geom as geom

    mesh = geom.Mesh()
    mesh.refresh()
    dp = mesh.disk_provider(dev[5:])

    for pp in mesh.partition_providers:
        if pp.label == 'journallog' and not force:
            print 'journallog partition already exists!' \
                          ' To create new journallog partition use -f'
            return

    if dp is not None:
        # IDE disks with partitions cannot be used for journallog
        if disk.is_bootdisk(dp):
            pg = dp.partition_geom
            if pg != None:
                if len(pg.providers) != 0:
                    print "cannot use a bootdisk for jlog\n"
                    return
        if disk.is_storage_disk(dp):
            # Smart fail this drive
            smart_fail(dev)
        disk.set_jlog_device(dev[5:])
        return

def disable_logging():
    subprocess.call(['/sbin/sysctl', 'efs.jlog.disable_logging'])
    subprocess.call(['/etc/rc.d/isi_create_hardware_xml', '-d', 'jlog_disable'])

def main():
    dev = None
    force = True

    opts, args = getopt.getopt(sys.argv[1:], 'fsd:')
    for opt, val in opts:
        if opt == '-f':
            force = True
        elif opt == '-s':
            disable_logging()
            return
        elif opt == '-d':
            dev = val

    if dev == None or not os.path.exists(dev):
       usage()
       return

    try:
        import isi.sys.bootdisk as bootdisk
        if (bootdisk.current_system_is_geom() or
            bootdisk.future_system_is_geom()):
            gpart_drive_format(dev, force)
    except:
        print "isi_jlog failed!\n"

def smart_fail(dev):
    child = subprocess.Popen(['isi', 'devices'], stdout=subprocess.PIPE)
    child.wait()
    ln = child.stdout.readline()

    bay_re = re.compile('Bay \d*')
    nodenum_re = re.compile('Node \d*')

    while ln != "":
        if ln.find('Node') != -1:
            node = int(nodenum_re.search(ln).group().strip('Node'))
        if ln.find(dev) != -1:
            print "matched: " + ln + "\n"
            bay = int(bay_re.search(ln).group().strip('Bay'))
            break
        ln = child.stdout.readline()
    child.stdout.close()

    isi_dev = "%s:%s"%(node,bay)

    ch = subprocess.Popen(['isi', 'devices', '-d', isi_dev], stdout=subprocess.PIPE)
    ln = ch.stdout.read(256)
    if ln.find('NEW') != -1:
        return
    if ln.find('REPLACE') != -1:
        return

    try:
        subprocess.check_call(['isi', 'devices', '-a', 'smartfail', '-d', isi_dev])
    except:
        pass

    done = False
    while not done:
        ch = subprocess.Popen(['isi', 'devices', '-d', isi_dev], stdout=subprocess.PIPE)
        ln = ch.stdout.read(256)
        if ln.find('NEW') != -1:
            return
        if ln.find('REPLACE') != -1:
            return
        time.sleep(1)

if __name__ == '__main__':
    main()
