#!/usr/bin/python

#    Copyright (c) 2009-2010 Gluster, Inc. <http://www.gluster.com>
#    This file is part of GlusterFS.

#    GlusterFS is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published
#    by the Free Software Foundation; either version 3 of the License,
#    or (at your option) any later version.

#    GlusterFS is distributed in the hope that it will be useful, but
#    WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#    General Public License for more details.

#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see
#    <http://www.gnu.org/licenses/>.


import getopt, sys, os, string
from optparse import OptionParser,OptionGroup,make_option

prefix = "/usr"

if not (prefix + "/share/glusterfs") in sys.path:
    sys.path.append(prefix + "/share/glusterfs")

from CreateVolfile import *
from Common import *

def generate_volume_files ():

    usage_str = "%s%s" % ("%prog: -n <VOLUMENAME> -t <TRANSPORT> -p <NUMBER> -a <AUTH> ",
                          "-r <TYPE> [--num-replica N] [--num-stripe N]")
    version_str = "%prog 3.0"
    desc_str = "A tool to generate volume files for GlusterFS."

    parse = OptionParser(usage=usage_str, version=version_str, description=desc_str)

    # Basic option list
    group = OptionGroup(parse, "Basic Options")
    group.add_option("-n", "--name", dest="volume_name",
                help="<volume-name>")
    group.add_option("-t", "--transport", dest="transport_type",
                default="tcp", help="tcp,ib-verbs default: tcp")
    group.add_option("-p", "--port", type="int",
                dest="port", help="<port> number")
    group.add_option("--auth", dest="auth_param", default="*",
                help="comma seperated ip range")
    group.add_option("-r", "--raid", type="int", dest="raid_type",
                help="0|1")
    group.add_option("-c", "--conf-dir", dest="conf_dir",
                     default=os.getcwd(),
                     help="output directory for volume files")
    group.add_option("--nfs", action="store_true", dest="need_nfs",
                default=False, help="enable nfs translator")
    parse.add_option_group(group)

    # Advanced option list
    group = OptionGroup(parse, "Advanced Options")
    group.add_option("--ibdev", type="int", dest="ib_dev",
                     default=1, help="Infiniband device number <N>")
    group.add_option("--volume-size-server", dest="size_server",
                     help="volume size for each server")
    group.add_option("--volume-size-client", dest="size_client",
                     help="volume size for each client")
    group.add_option("--safe-mode", action="store_true",
                     dest="enable_safe_mode", default=False,
                     help="generate volume files in safe mode")
    group.add_option("--num-replica", type="int", dest="num_replica",
                     help="number of file replica needed")
    group.add_option("--num-stripe", type="int", dest="num_stripe",
                     help="number of stripe count needed")
    group.add_option("--portmapper-mode", action="store_true", dest="portmapper",
                     default=False, help="generate volume files for glusterfs portmapper friendly way")

    parse.add_option_group(group)

    # Changes for Dynamic Volume Manager
    #group = OptionGroup(parse, "Dynamic Volume Options")
    #group.add_option("--add-server", dest="add_server_args",
    #                 help="Add server to existing volume")
    #group.add_option("--migrate", dest="migrate_server_args",
    #                 help="Migrate servers from existing volumes")

    #parse.add_option_group(group)

    (options, args) = parse.parse_args()

    if options.volume_name is None:
        print "Error: volume name is mandatory, please provide volume name"
        raise ValueError

    if options.need_nfs and options.size_client:
        print "Error: Currently quota not supported with native NFS, please use server side instead"
        raise ValueError

    if options.transport_type:
        transports = options.transport_type.split(',')
        for transport in transports:
            if (transport != "tcp" and transport != "ib-verbs"):
                print "Error: --transport: option " + transport + \
                    " is not valid transport type"
                raise ValueError

    if options.raid_type:
        if (options.raid_type != 1 and options.raid_type != 0):
            print "Error: --raid: option " + str(options.raid_type) + " is not valid raid type"
            raise ValueError

    if options.conf_dir:
        if not os.path.isdir(options.conf_dir):
            print "Specified directory %s doesn't exist" % options.conf_dir
            raise ValueError

    server_dict = {}

    # Dynamic Volume Manager
    #if options.add_server_args:
    #    add_server_list = (options.add_server_args).strip().split()
    #    check_duplicate_entry(add_server_list)
    #    old_server_list = get_old_server_args(list_export_vols(options.conf_dir,
    #                                                           options.volume_name),
    #                                          options.conf_dir)
    #    for new_server in add_server_list:
    #        old_server_list.append(new_server)

    #    server_dict = args2dict(old_server_list)
    #    server_array = args2array(old_server_list)

    #    if len (server_dict.keys()) == 0:
    #        print "Error: no servers provided, please provide atleast one server"
    #        raise ValueError

    #else:
    check_duplicate_entry(args)
    server_dict = args2dict(args)
    server_array = args2array(args)

    if len (server_dict.keys()) == 0:
        print "Error: no servers provided, please provide atleast one server"
        raise ValueError

    if options.num_replica is None:
        options.num_replica = 2

    if options.num_stripe is None:
        options.num_stripe = 4

    if options.num_replica < 2:
        print "--num-replica option (%d) is not valid" % options.num_replica

    if options.num_stripe < 2:
        print "--num-stripe option (%d) is not valid" % options.num_stripe

    if options.raid_type == 1:
        if (len(server_array) % options.num_replica) != 0:
            print "raid type (%d) and number of volumes (%d) invalid" % (options.raid_type,
                                                                         len(server_array))
            raise ValueError

    if options.raid_type == 0:
        if (len(server_array) % options.num_stripe) != 0:
            print "raid type (%d) and number of volumes (%d) invalid" % (options.raid_type,
                                                                         len(server_array))
            raise ValueError

    if options.portmapper is True:
        for server in server_dict.keys():
            create_exp = CreateVolfile (server_dict, server,
                                        None, transports,
                                        options, None)
            try:
                create_exp.create_pmap_export_volfile ()
            except IOError, (errno, strerror):
                print "Got %s creating server volfiles for %s" % (strerror, server)

        for transport in transports:
            create_mnt = CreateVolfile (server_dict, None,
                                        transport, transports,
                                        options, server_array)
            try:
                create_mnt.create_pmap_mount_volfile ()
            except IOError, (errno, strerror):
                print "Got %s creating client volfiles for transport '%s'" % (strerror, transport)

        if options.need_nfs:
            for transport in transports:
                create_mnt = CreateVolfile (server_dict, None,
                                            transport, transports,
                                            options, server_array)
                try:
                    create_mnt.create_pmap_nfs_volfile ()
                except IOError, (errno, strerror):
                    print "Got %s creating nfs volfiles for transport '%s'" % (strerror, transport)

        return

    for server in server_dict.keys():
        create_exp = CreateVolfile (server_dict, server,
                                    None, transports,
                                    options, None)
        try:
            create_exp.create_export_volfile ()
        except IOError, (errno, strerror):
            print "Got %s creating server volfiles for %s" % (strerror, server)

    for transport in transports:
        create_mnt = CreateVolfile (server_dict, None,
                                    transport, transports,
                                    options, server_array)
        try:
            create_mnt.create_mount_volfile ()
        except IOError, (errno, strerror):
            print "Got %s creating client volfiles for transport '%s'" % (strerror, transport)


def main ():

    try:
        generate_volume_files()
    except ValueError:
        sys.exit(1)


main()
