#!/usr/bin/env python
#
# Script to force a reboot of a node by sending a command via the RBM,
# replacing need for Support or customer to directly execute a test thread

import getopt
import os
import sys

import isi.config.array as array
import isi.misc as misc

def usage(exitCode):
    sys.stderr.write(r'''
Usage: ''' + os.path.basename(sys.argv[0]) + r''' [OPTION]... NODE

Options:
  -i, --id                  Interpret node number by as an Array ID
                            Mutually exclusive with --lnn.
  -l, --lnn                 Interpret node number as LNN (default)
                            Mutually exclusive with --id.
  -m, --message MESSAGE     Use MESSAGE as the panic message in the logs
  -h, --help                Print this message and exit
''')
    sys.exit(exitCode)

def main():

    useLNN=True
    explicitID=False
    explicitLNN=False
    panicMessage = "Support forcing panic"

    try:
        opts, args = getopt.gnu_getopt(sys.argv[1:], 'hilm:',
            ['help','id','lnn','message='])
        for o, a in opts:
            if o in ['-h', '--help']:
                usage(0)
            if o in ['-i', '--id']:
                if explicitLNN: usage(1)
                explicitID = True
                useLNN=False
            if o in ['-l', '--lnn']:
                if explicitID: usage(1)
                explicitLNN = True
                useLNN=True
            if o in ['-m', '--message']:
                panicMessage = a
    except getopt.GetoptError:
        usage(1)
        
    # We should have exactly one argument, and it should be an integer.
    if len(args) == 1:
        try:
            rebootme = int(args[0])
        except ValueError:
            usage(1)
    else:
        usage(1)
    
    # If we're using an LNN, convert to array ID. Otherwise, it is an ID.
    cluster = array.getArray()
    if useLNN:
        reboot_node = cluster.findNodeByLNN(rebootme)
    else:
        reboot_node = cluster.nodes.findByDevid(rebootme)

    # If we got an object back, we can reboot; otherwise, it's not real
    if reboot_node:
        node_id = str(reboot_node.id())
    else:
        print >>sys.stderr, "Node", rebootme, "not in cluster."
        sys.exit(1)

    # Sanitize the panic message
    invalid_chars=''';$\'\"\\`
'''
    message = ''.join(c for c in panicMessage if c not in invalid_chars)

    # Actually panic the node
    panic_thread = "rbm_panic(" + node_id + ", 0, \"" + message + "\")"
    misc.test_thread(panic_thread)

if __name__ == '__main__':
    main()
