#!/usr/bin/env python
#
# Copyright C 2002-2006 by Isilon Systems, Inc. All rights not expressly
# granted herein are reserved.
# Created in the United States of America.
# 
# This digital media is protected by U.S. and international copyright and
# intellectual property laws. Unless otherwise specified, all information
# and screens appearing as part of this digital medium, including
# software, services, documents, text, images, icons, and logos design;
# the selection, assembly, arrangement, and design thereof; and the code
# that enables its presentation, are the sole property of Isilon Systems,
# Inc.
# 
# Except as otherwise required by applicable law, no part of any
# copyrighted material may be reproduced, modified, translated,
# distributed, published, or transmitted by any means, electronic or
# mechanical, for any purpose, without the prior written consent of Isilon
# Systems. 
#  
# Isilon and Isilon Systems are registered trademarks of Isilon Systems,
# Inc.  Legion is a trademark of Isilon Systems, Inc.  All other
# trademarks and registered trademarks are the property of their
# respective holders.
#
# $Id: isi_get_license 416586 2014-06-13 20:38:17Z ssoumpholphakdy $
#
# This script is for internal licensing purposes.  See the wiki for more info:
# http://wiki/index.php?title=Licensing_Development_Process
#

import httplib
import os
import sys
import getopt
import urllib2
import re
import time

import isi.config.licensing as lic
import isi.papi.cloudpool_handlers as cp
import isi.config.swift as swift_config

LICENSE_URL = 'http://licensing.west.isilon.com/internal-license.php'
DEFAULT_MODULES_MASK = 0xaf

LICENSING_DIR = "/etc/ifs/licensing"

def fatal(error):
    print >> sys.stderr, error
    sys.exit(-1)

def verbose(print_verbose, message):
    if (print_verbose):
        print >> sys.stderr, message

def usage():
    fatal('usage: %s [-hpvc] [-M mask] [-m module1,module2,...]' % sys.argv[0])

def main(args):
    try:
        opts, list = getopt.getopt(args, "hpvcM:m:")
        opts = dict(opts)
    except:
        usage()

    if not len(list) == 0:
        usage()

    print_verbose = opts.has_key('-v')
    print_only = opts.has_key('-p')

    modules = {}
    modules_mask = 0
    all_modules_mask = 0

    if not print_only:
        try:
            import isi.config.licensing as lic
        except ImportError:
            print "On non-Isilon systems, can only use -p to get default key."
            usage()
        for f in os.listdir(LICENSING_DIR):
            try:
                with open("%s/%s" % (LICENSING_DIR, f)) as fo:
                    lines = map(lambda s: s.strip(), fo.readlines())
                    modules[lines[1].lower()] = [lines[1], int(lines[0], 0),
                            lic.NONE]
            except Exception, e:
                print "Failed to open licensing file %s: %s" % (f, e)
        # Fill in the states
        for module, state, date, term in lic.get_modules():
            try:
                modules[module.lower()][2] = state
                all_modules_mask |= modules[module.lower()][1]
            except:
                pass

    if '-h' in opts:
        if modules:
            print "Available modules:"
            for module in modules:
                if modules[module][2] == lic.VALID:
                    status = 'licensed'
                elif modules[module][2] == lic.EXPIRED:
                    status = 'expired'
                elif modules[module][2] == lic.NONE:
                    status = 'not licensed'
                else:
                    status = 'unknown: %s' % `modules[module][2]`
                print "%30s    status: %15s" % (modules[module][0], status)
            print
        usage()

    if '-m' in opts and '-M' in opts:
        print "Invalid options: -M and -m cannot be supplied together"
        usage()
    elif '-m' in opts:
        for module in opts['-m'].split(','):
            module = module.lower().replace('_', ' ')
            if not module in modules.keys():
                fatal('Module "%s" not recognized.' % module)
            else:
                modules_mask |= modules[module][1]
    elif '-M' in opts:
        try:
            modules_mask = int(opts['-M'], 0)
        except ValueError:
            print "Could not parse modules mask: %s" % opts['-M']
            usage()
    elif all_modules_mask:
        modules_mask = all_modules_mask
    else:
        modules_mask = DEFAULT_MODULES_MASK

    try:
        verbose(print_verbose, 'Attempting to retrieve %s' % LICENSE_URL)
        verbose(print_verbose, 'Using module mask of 0x%x' % modules_mask)

        attempt = 1
        max_tries = 5
        while True:
            try:
                f = urllib2.urlopen('%s?modules=0x%x'
                                    % (LICENSE_URL, modules_mask),
                                    None, 20)
                key = f.read().strip()
                f.close()
            except httplib.BadStatusLine as e:
                if attempt <= max_tries:
                    attempt += 1
                    # Server tossed back a bad header, etc potentially due to a
                    # bad connection; try again..
                    continue
                raise
            except urllib2.URLError as e:
                if str(e).find('timed out') != -1 and attempt <= max_tries:
                    attempt += 1
                    # Connection timed out looking for a response; try again..
                    continue
                raise
            # Got a key; break out of the loop
            break
    except IOError, e:
        fatal('Failed to retrieve URL: %s' % str(e))

    verbose(print_verbose, 'Checking validity of retrieved key')
    if not re.match('^ILLEG-AL\w{3}(-\w{5}){3}$', key):
        fatal('Server returned invalid key.')

    if print_only:
        if '-M' in opts:
            print "License key for module mask %s:" % opts['-M']
        else:
            print "Default module selection key:"
        print key
    else:
        verbose(print_verbose, 'Adding key to cluster')
        verbose(print_verbose, key)
        # Clear old license file for bug 74152
        if '-c' in opts:
            try:
                verbose(print_verbose, 'Clearing old license file')
                os.remove(lic.LICENSING_MXD_OVERRIDE_FILE)
            except:
                pass
        ret = lic.add_key(key)
        if ret != 0:
            fatal('Failed to add key (%d)' % ret)
        else:
            if lic.valid_key_for_module(key, lic.CLOUDPOOLS):
                cp.activate_cloudpools()
            if lic.valid_key_for_module(key, lic.SWIFT):
                swift_config.activate_swift()
        time.sleep(1)

if __name__ == '__main__':
    main(sys.argv[1:])
