"""Routines that perform operations related to gluster's trusted storage pool.

This exports:

  get_peer_list - Get a list of all the gluster peers excluding the localhost.
  remove_a_gridcell_from_gluster_pool - Remove a gridcell from the trusted storage pool.
  add_a_gridcell_to_gluster_pool - Add a gridcell to the trusted storage pool.
  get_gridcells_not_in_trusted_pool - Return a list of gridcells that are available to be pulled into the trusted pool. 

"""

import socket
from integralstor_gridcell import xml_parse
from integralstor_utils import networking


def get_peer_list():
    """Get the list of all the gluster peers to this node.

    If the command runs without an error, it returns a list of peers
    """

    peer_list = None
    try:
        cmd = '/usr/sbin/gluster peer status --xml'
        d, err = xml_parse.run_gluster_command(cmd)
        if err:
            raise Exception(err)
        peer_list = None
        if d and 'root' in d and d['root']:
            peer_list, err = xml_parse.get_peer_list(d["root"])
            if err:
                raise Exception(err)
    except Exception, e:
        return None, 'Error getting peer list: %s' % str(e)
    else:
        return peer_list, None


def remove_a_gridcell_from_gluster_pool(hostname):
    """Given a hostname, it attempts to removes that hostname from the gluster trusted storage pool.

    If the command runs without an error, it returns a dict with the return status and the xml root
    """
    d = None
    try:
        if not hostname:
            raise Exception('Required parameter not passed')
        localhost = socket.getfqdn().strip()
        if hostname != localhost:
            d = {}
            cmd = 'gluster peer detach %s --xml' % hostname
            d, err = xml_parse.run_gluster_command(cmd)
            if err:
                raise Exception(err)
    except Exception, e:
        if hostname:
            return None, "Error removing GRIDCell %s from the storage pool : %s" % (hostname, e)
        else:
            return None, "Error removing GRIDCell from the storage pool : %s" % (e)
    else:
        return d, None


def add_a_gridcell_to_gluster_pool(hostname):
    """Given a hostname, it attempts to add that hostname to the gluster trusted storage pool.

    If the command runs without an error, it returns a dict with the return status and the xml root
    """
    d = None
    try:
        localhost = socket.getfqdn().strip()

        status_dict = None
        if hostname != localhost:
            cmd = "gluster peer probe %s --xml" % hostname
            # print 'executing gluster cmd'
            d, err = xml_parse.run_gluster_command(cmd)
            if err:
                raise Exception(err)
        else:
            raise Exception(
                "The GRIDCell %s is the localhost and hence already part of the pool" % hostname)
    except Exception, e:
        if hostname:
            return None, "Error adding GRIDCell %s to the storage pool : %s" % (hostname, e)
        else:
            return None, "Error adding GRIDCell to the storage pool : %s" % (e)
    else:
        return d, None


def get_gridcells_not_in_trusted_pool(si):
    """Return a list of gridcells that are available to be pulled into the trusted pool. 

    Returns a list of dicts with the hostname and the system_info dicts
    si - The system info dict to check the system for its current status.
    """

    nl = []
    try:
        if not si:
            raise Exception('Required parameters not passed')
        for hostname, gridcell_info in si.iteritems():
            if gridcell_info["in_cluster"]:
                continue
            d = {}
            d["hostname"] = hostname
            d["host_info"] = gridcell_info
            nl.append(d)
    except Exception, e:
        return None, 'Error retrieving available GRIDCell list : %s' % str(e)
    else:
        return nl, None


def can_remove_gridcell_from_storage_pool(hostname, admin_gridcells, si):
    '''Determine if a node can be removed from the storage pool or not

    hostname - the gridcell hostname in question
    si - The system info dict. If not passed, we generate it
    '''
    ret = False
    try:
        if not hostname:
            raise Exception('No hostname provided')
        localhost = socket.getfqdn().strip()
        # if hostname != localhost and (hostname not in
        # ['gridcell-sec.integralstor.lan', 'gridcell-pri.integralstor.lan'])
        # and si[hostname]["in_cluster"] and (not si[hostname]["volume_list"]):
        if hostname != localhost and (hostname not in admin_gridcells) and si[hostname]["in_cluster"] and (not si[hostname]["volume_list"]):
            ret = True
    except Exception, e:
        return False, 'Error checking for GRIDCell removal from storage pool : %s' % str(e)
    else:
        return ret, None


def can_add_gridcell_to_storage_pool(hostname, si=None):
    '''Determine if a node can be added to the storage pool or not

    hostname - the gridcell hostname in question
    si - The system info dict. If not passed, we generate it
    '''
    ret = False
    try:
        if not hostname:
            raise Exception('No hostname provided')
        if not si:
            si, err = load_system_config()
            if err:
                raise Exception(err)

        # Can add if not in trusted pool.
        nl, err = get_gridcells_not_in_trusted_pool(si)
        if err:
            raise Exception(err)
        if nl:
            for n in nl:
                # Can add if not in the trusted pool and the node status is ok.
                if n['hostname'] == hostname:
                    # if si[hostname]['node_status'] == 0:
                    if networking.can_ping(hostname):
                        ret = True
                    break
    except Exception, e:
        return False, 'Error checking for GRIDCell addition to the storage pool : %s' % str(e)
    else:
        return ret, None

# vim: tabstop=8 softtabstop=0 expandtab ai shiftwidth=4 smarttab
