#!/usr/bin/python

# PROVIDE: isi_dongle_init
# REQUIRE: isi_bootdisk_init syslogd isi_hal_init

import os
import isi.hw.version as hwver
import isi.hw.dongle as hwdongle

# This function is copied from isi_dongle_sync
def display():
    dongle_info = hwdongle.dongle_info()
    line = "Dongle serial number: "
    if (dongle_info == None or 'serialno' not in dongle_info):
        line += "Unknown"
    else:
        line += dongle_info['serialno']

    print(line)

    line = "Dongle system configuration: "
    if (dongle_info == None or 'sysconfig' not in dongle_info):
        line += "Unknown"
    else:
        line += dongle_info['sysconfig']

    print(line)
    return 0

def main():
    if hwver.hwgen in [hwver.HWGEN_GENERIC]:
        # Don't bother hard-coded always write of SKU/SERNO, rely on user
        # Return early, hard-coded to not support dongles on GENERIC
        return

    #
    # A chassis contains VPD identifying the chassis SKU, serial
    # number, etc. There are two (2) copies of this VPD; one that
    # lives in a dongle/EEPROM in the chassis itself and one that
    # lives on the hard disks in files named "/etc/isilon_*". 
    #
    # The copy of the information that lives in the chassis itself
    # is normally considered the more correct version of the data,
    # so the information in the chassis needs to be synchronized
    # with the copy on the hard disks.
    #
    # Initially, when nodes and drives complete the MFG process, one 
    # of the last steps performed is a "factory reset". This step prepares
    # the node for shipment, as well as marking the drives as "install
    # drives". The next time the node is powered on with these "install
    # drives", the chassis will either have a product SKU already (2U), 
    # or one will be assigned (4U) to it through SKU transformation.  
    #
    # When a disk tango operation is performed in the field to repair
    # a failed chassis (4U), the disks are moved from the failed
    # chassis into a new spare. The VPD on the hard disks needs to
    # be preserved at least long enough to complete the disk tango
    # successfully, at which time the information in both places
    # will be updated. 
    #
    print 'Determining if dongle sync is needed...'

    print 'Checking for factory fresh drives...'
    if (os.path.exists("/etc/ifs/isi_factory_fresh_drives")):
        factory_fresh_drives = True
        print 'Drives are factory fresh.'
    else:
        factory_fresh_drives = False
        print 'Drives are not factory fresh.'

    print 'Checking for SKU on disks...'
    if (os.path.exists("/etc/isilon_system_config")):
        sku_exists_on_disks = True
        infile = open("/etc/isilon_system_config", "r")
        sku = infile.readline()
        print 'SKU (%s) exists on disks.' % sku.rstrip('\n')
    else:
        sku_exists_on_disks = False
        print 'SKU does not exist on disks.'

    print 'Checking if SKU transformation is needed...'
    if (os.system("/usr/bin/isi_transform_tool --need")):
        sku_transformation_needed = True
        print 'SKU transformation is needed.'
    else:
        sku_transformation_needed = False
        print 'SKU transformation is not needed.'

    #
    # Logic truth table
    #
    # Legend:
    # -------
    #   812                         = 3/4 chassis
    #   851                         = product chassis
    #   sku_exists_on_disks         = sod
    #   factory_fresh_drives        = ffd
    #   sku_transformation_needed   = stn
    #   dongle_sync_needed          = dsn
    #
    # sod ffd stn dsn comments
    # --- --- --- --- --------
    #  N   N   N   Y  851: SKU has somehow been lost from disks
    #  N   N   Y   Y  812: MFG or reimage of clean disks
    #  N   Y   N   Y  851: install drives being put in product
    #  N   Y   Y   Y  812: install drives being put in 3/4 chassis
    #  Y   N   N   Y  851: normal boot of product
    #  Y   N   Y   N  812: disk tango
    #  Y   Y   N   N  851: invalid factory reset removes /etc/isilon*
    #  Y   Y   Y   N  812: invalid factory reset removes /etc/isilon*
    #
    if (not sku_exists_on_disks) or \
        (not factory_fresh_drives and not sku_transformation_needed):

        print 'A dongle sync is needed.'
        dongle_sync_needed = True
    else:
        print 'A dongle sync is not needed.'
        dongle_sync_needed = False

    if dongle_sync_needed:
        print 'Synchronizing with dongle/EEPROM...'

        # Not a disk tango, so go ahead and synchronize dongle 
        # (and EEPROM) with local file system files
        # XXX Consider: Should we skip this, always, for mfg boots?
        #     (For all cases: dongle, eeprom, or dongle+eeprom)
        try:
            print 'Loading dongle/EEPROM...'
            errors = hwdongle.dongle_user_init()
            if errors:
                print 'Unable to load dongle/EEPROM.'
                for error in errors:
                    print error
            else:
                if hwdongle.dongle_sync():
                    # failed, probably needs an fsck
                    hwdongle.dongle_fix()
                    hwdongle.dongle_sync()
                    print 'Dongle/EEPROM synchronization complete.'
        except Exception, e:
            print "Error synchronizing with dongle/EEPROM: %s" % e
    else:
        print 'Skipping dongle/EEPROM synchronization'

    # Display and log the sysctem configuration from the dongle
    display()

if __name__ == '__main__':
    main()
