#!/usr/bin/python
"""
Binary to query clusterconfiguration
"""
__version__ = "$Revision: 1.13 $"
__description__="""
Binary to query clusterconfiguration
"""

import getopt
import sys
import logging
import os
import os.path

from comoonics import ComLog
from comoonics.ComExceptions import ComException

import comoonics.cluster
from comoonics.cluster.ComClusterInfo import ClusterInfo
from comoonics.cluster.ComClusterRepository import ClusterRepository, ClusterMacNotFoundException, RedHatClusterRepository
from comoonics.cluster.ComQueryMap import QueryMap

from xml.dom.ext.reader import Sax2

from optparse import OptionParser

ComLog.setLevel(logging.INFO)
usage = """
usage: %prog [options] query_command
query_commands are:
    query_xml <xq>           print out the xml_document specified by an XQL query string
    query_value <xql>        print out the value specified by an XQL query string
    convert type             converts the cluster repository to the given type (supported types are: ocfs2) 
    netdevs <hostname> [<sep>]
                             print out the network device names for given host. Separated by <sep>
    nodename <mac>           print out the nodename for given mac.
    nodenamebyid <id>        print out the nodename for given nodeid.
    nodeid <mac>             print out the nodeid for given mac.
    ip <nodename> <dev>      print out the IP address for given hostname and network device name
    master <nodename> <dev>  print out the master if for given hostname and network device name
    slave <nodename> <dev>   print out the slave for given hostname and network device name
    mask <nodename <dev>     print out the netmask for given hostname and network device name
    gateway <nodename <dev>  print out the gateway for given hostname and network device name
    hosts                    print out the the hosts in hosts file type
    ifconfig <mac>           print out the the ifconfig parameter for mac
    rootvolume <nodename>    print out the device name for the root device
    rootfs <nodename>        print out the filesystem name for the root device
    mountopts <nodename>     print out the mountoptions for the nodename
    syslog <nodename>        print out the syslog server
    failoverdomainnodes <failoverdomain> [<sep>]
                             print out all defined nodes in the given
                             failoverdomain. Seperated by sep default is space.
    failoverdomainprefnode <failoverdomain>
                             print out the preferred node defined in
                             the given failoverdomain.
    nodeids [<sep>]          returns all defined nodeids seperated by <sep>.
    scsifailover nodename    returns the scsifailovertype for the given nodename
        """
parser = OptionParser(usage=usage, description=__doc__)
parser=comoonics.cluster.commonoptparseroptions(parser)
# This is obsolete as it is always true but has to stay because of backwards compatibility
parser.add_option("-q", "--query", dest="query", default=True, action="store_true", help="Query the cluster")
# again because of compatibilities
# -c --clusterconf should be used.
parser.add_option("-f", "--filename", dest="clusterconf", default=RedHatClusterRepository.getDefaultClusterConf())
parser.add_option("-m", "--querymapfile", dest="mapfile", default=comoonics.cluster.querymapfile, help="External file for query mappings")
parser.add_option("-V", "--validate", dest="validate", default=False, action="store_true", help="Validate the cluster configuration if possible")

ComLog.setLevel(logging.INFO)
(options, args) = parser.parse_args()

if len(args) > 1:
    values = args[1:]
else:
    values = []
if len(args) > 0:
    query=args[0]
else:
    parser.error("Wrong number of arguments. At least one is required. None given.")
if not os.path.isfile(options.clusterconf):
    parser.error("Could not find clusterconfiguration file %s" %(options.clusterconf))

doc=comoonics.cluster.parseClusterConf(options.clusterconf, options.validate)

#create needed cluster objects
clusterRepository = ClusterRepository(doc.documentElement,doc)
clusterInfo = ClusterInfo(clusterRepository)
clusterQueryMap = QueryMap(options.mapfile, clusterInfo)

#query given file with specified query, returns xml
if query == "query_xml":
    print clusterInfo.queryXml(values[0])
    
#query given file with specified query, returns value
elif query == "query_value":
    print " ".join(clusterInfo.queryValue(values[0]))

#print clusters network devices by name, separated by value of options.netdevs    
elif query == "netdevs":
    if len(values) < 2:
        values.append(" ")
    _tmp = []
    for Nic in clusterInfo.getNode(values[0]).getNics():
        _tmp.append(Nic.getName())
    print values[1].join(_tmp)

#Query Nodename to given mac, raise exception if mac not found
elif query == "nodename":
    print clusterInfo.getNodeName(values[0])
    
#Query Nodename to given id, raise exception if id not found
elif query == "nodenamebyid":
    print clusterInfo.getNodeNameById(values[0])

#Query Nodeid to given mac, raise exception if mac not found
elif query == "nodeid":
    print clusterInfo.getNodeId(values[0])
    
#print ip of given node and given device
elif query == "ip":
    _node = clusterInfo.getNode(values[0])
    _nic = _node.getNic(values[1])
    print _nic.getIP()

#print ip of given node and given device
elif query == "master":
    _node = clusterInfo.getNode(values[0])
    _nic = _node.getNic(values[1])
    print _nic.getMaster()

#print ip of given node and given device
elif query == "slave":
    _node = clusterInfo.getNode(values[0])
    _nic = _node.getNic(values[1])
    print _nic.getSlave()

#print ip of given node and given device
elif query == "mask":
    _node = clusterInfo.getNode(values[0])
    _nic = _node.getNic(values[1])
    print _nic.getNetmask()

#print ip of given node and given device
elif query == "gateway":
    _node = clusterInfo.getNode(values[0])
    _nic = _node.getNic(values[1])
    print _nic.getGateway()

#print list of clusters host with if and name
#FIXME: Returns only first ip-address<->name pair of every clusternode to avoid duplicate entries for the same hostname
elif query == "hosts":
    for node in clusterInfo.getNodes():
        for Nic in node.getNics():
            if Nic.getIP() != "" and Nic.getIP() != "dhcp":
                print Nic.getIP() +  "\t" + node.getName()
                break

#print ifconfig for given mac, raise exception if mac not found
elif query == "ifconfig":
    _macfound = False
    for node in clusterInfo.getNodes():
        if node.nicMac.has_key(values[0]):
            _nic = node.nicMac[values[0]]
            print _nic.getName() + " " + _nic.getIP() + " " + _nic.getNetmask()
            _macfound = True
    if _macfound == False:
        raise ClusterMacNotFoundException("Cannot find mac " + values[1])

#print rootvolume of node with given name
elif query == "rootvolume":
    print clusterInfo.getNode(values[0]).getRootvolume()

#print rootfs of node with given name
elif query == "rootfs":
    print clusterInfo.getNode(values[0]).getRootFs()
    
#print mount options of node with given name
elif query == "mountopts":
    print clusterInfo.getNode(values[0]).getMountopts()

#print syslog of node with given name
elif query == "syslog":
    print clusterInfo.getNode(values[0]).getSyslog()

#print failoverdomainnodes belonging to given failoverdomain, seperated by <sep>
elif query == "failoverdomainnodes":
    if len(values) < 2:
        values.append(" ")
    print values[1].join(clusterInfo.getFailoverdomainNodes(values[0]))

#prints prefered failover node belonging to given failoverdomain
elif query == "failoverdomainprefnode":
    if len(values) < 1:
        values.append(" ")
    print clusterInfo.getFailoverdomainPrefNode(values[0])

#print list of nodeids, seperated by given value
elif query == "nodeids":
    if len(values) < 1:
        values.append(" ")
    _tmp = []
    for node in clusterInfo.getNodes():
        _tmp.append(node.getId())
    print values[0].join(_tmp)

#print scsifailover of node with given name
elif query == "scsifailover":
        print clusterInfo.getNode(values[0]).getScsifailover()
    
elif query == "convert":
    print clusterInfo.clusterRepository.convert(values[0])

elif clusterQueryMap.has_option(clusterQueryMap.mainsection, query):
    print " ".join(clusterInfo.queryValue(clusterQueryMap.get(clusterQueryMap.mainsection, query) % clusterQueryMap.array2params(values)))
    
else:
    raise NameError("Cannot find query named " + query)
