#!/usr/bin/python

import getopt, sys
import socket, ssl
from xml.dom import minidom
import logging
import os
import os.path

RICCI_PORT = 11111
CLUSTERRNG = "cluster.rng.in"

password = None
debug = False
propagate = False

def main(argv):
    hostname = "localhost"
    getconf = False
    status = fence = start = stop = False
    listnodes = listservices = listdomains = False
    addnode = removenode = getversion = False
    incrementversion = setversion = False
    addmethod = removemethod = createcluster = False
    addfencedev = removefencedev = False
    addfenceinst = removefenceinst = False
    lsfencedev = lsfenceinst = False
    addfailoverdomain = removefailoverdomain = False
    addservice = False
    addsubservice = False
    passwordset = False
    global password
    global debug
    global propagate
#    logging.basicConfig(level=logging.DEBUGRemove
    try:
        opts, args = getopt.getopt(argv, "dh:p:", ["help","host=","getconf","status","fence=","start","stop","lsnodes",
      "lsservices", "listdomains", "addnode=", "removenode=", "getversion","setversion=","incversion",
      "createcluster=", "password=", "addmethod=", "removemethod=", "addfencedev=", "removefencedev=",
      "addfenceinst=", "removefenceinst=", "lsfencedev", "lsfenceinst=", "propagate", "addfailoverdomain=",
      "removefailoverdomain=", "addservice=", "addsubservice="])
    except getopt.GetoptError:
        usage()
        sys.exit(2)
    for opt, arg in opts:
        if opt == ("--help"): usage() ; sys.exit()
        elif opt in ("--host","-h"):
            hostname = arg
            logging.debug("Hostname = %s" % hostname)
        elif opt in ("--password", "-p"): passwordset = True ; password = arg
        elif opt in ("--getconf"): getconf = True
        elif opt in ("--status"): status = True
        elif opt in ("--fence"): fence = True ;  node = arg
        elif opt in ("--start"): start = True
        elif opt in ("--stop"): stop = True
        elif opt in ("--lsnodes"): listnodes = True
        elif opt in ("--lsservices"): listservices = True
        elif opt in ("--listdomains"): listdomains = True
        elif opt in ("--addnode"): addnode = True ; node = arg 
        elif opt in ("--removenode"): removenode = True ; node = arg 
        elif opt in ("--getversion"): getversion = True
        elif opt in ("--setversion"): setversion = True ; version = arg 
        elif opt in ("--incversion"): incrementversion = True
        elif opt in ("--propagate"): propagate = True
        elif opt in ("--createcluster"):
            createcluster = True
            clustername = arg
        elif opt in ("--addmethod"):
            addmethod = True
            method = arg
            options = args
        elif opt in ("--removemethod"):
            removemethod = True
            method = arg
            options = args
        elif opt in ("--addfencedev"):
            addfencedev = True
            name = arg
            options = args
        elif opt in ("--removefencedev"): removefencedev = True; name = arg
        elif opt in ("--addfenceinst"):
            addfenceinst = True
            name = arg
            options = args
        elif opt in ("--removefenceinst"):
            removefenceinst = True
            name = arg
            options = args
        elif opt in ("--lsfencedev"): lsfencedev = True;
        elif opt in ("--lsfenceinst"): lsfenceinst = True; instance = arg
        elif opt in ("--addfailoverdomain"):
            addfailoverdomain = True
            name = arg
            options = args
        elif opt in ("--removefailoverdomain"): removefailoverdomain = True; name = arg
        elif opt in ("--addservice"):
            addservice = True
            name = arg
            options = args
        elif opt in ("--addsubservice"):
            addsubservice = True
            name = arg
            options = args
        elif opt in ("-d"): debug = True

    if (getconf): get_cluster_conf(hostname)
    if (status): get_cluster_status(hostname)
    if (fence): fence_node(hostname, node)
    if (stop): stop_node(hostname) 
    if (start): start_node(hostname)
    if (listnodes): list_nodes(hostname)
    if (listservices): list_services(hostname)
    if (listdomains): list_domains(hostname)
    if (addnode): add_node(hostname, node)
    if (removenode): remove_node(hostname, node)
    if (getversion): print get_version(hostname)
    if (setversion): set_version(hostname, version)
    if (incrementversion): increment_version(hostname)
    if (createcluster): create_cluster(hostname, clustername)
    if (addmethod): add_method(hostname, method, options)
    if (removemethod): remove_method(hostname, method, options)
    if (addfencedev): add_fencedev(hostname, name, options)
    if (removefencedev): remove_fencedev(hostname, name)
    if (addfenceinst): add_fenceinst(hostname, name, options)
    if (removefenceinst): remove_fenceinst(hostname, name, options)
    if (lsfencedev): ls_fencedev()
    if (lsfenceinst): ls_fenceinst(arg)
    if (addfailoverdomain): add_failoverdomain(hostname, name, options)
    if (removefailoverdomain): remove_failoverdomain(hostname, name)
    if (addservice): add_service(hostname, name, options)
    if (addsubservice): add_subservice(hostname, name, options)

def usage():
    print """Usage: ccs [OPTION]...
Remotely control cluster infrastructure.

      --help            Display this help and exit
  -h, --host            Ricci host to connect to (defaults to localhost)
  -p, --password        Root password for node running ricci
      --getconf         Print current cluster.conf file
      --status          Print current cluster status
      --createcluster <cluster>
                        Create a new cluster.conf
      --addnode <node>  Add node <node> to the cluster
      --removenode <node>
                        Remove a node from the cluster
      --addmethod <method> <node>
                        Add a method to a specific node
      --removemethod <method> <node>
                        Remove a method from a specific node
      --addfencedev <device> <options>
                        Add fence device
      --removefencedev <fence device name>
                        Remove fence device
      --addfenceinst <fence device name> <node> <method> <options>
                        Add fence instance
      --removefenceinst <fence device name> <node> <method>
                        Remove all instances of the fence device listed from
                        the given method and node
      --addfailoverdomain <name> [restricted] [ordered] [nofailback]
                        Add failover domain
      --removefailoverdomain <name>
                        Remove failover domain
      --addfailoverdomainnode <failover domain> <node> [priority=xx]
                        Add node to given failover domain
      --addservice <servicename> [service options] ...
                        Add service to cluster
      --addsubservice <servicename> <service type> [service options] ...
                        Add individual services
      --lsfencedev      Lists available fence devices and their options
      --lsfenceinst <fence device>
                        Lists available fence instances options for given
                        fence device
      --lsnodes         List all nodes in the cluster
      --lsservices      List all services in the cluster
      --start           Start cluster services on host
      --stop            Stop cluster services on host
      --fence <node>    Fence the node <node>
      --getversion      Get the current cluster.conf version
      --setversion      Set the cluster.conf version
      --incversion      Increment the cluster.conf version by 1
                        scp and put them in the current directory
  """

def fence_node(hostname, node):
    xml = send_ricci_command(hostname, "cluster", "fence_node",("nodename","string",node)) 
    print xml
    
def stop_node(hostname):
    xml = send_ricci_command(hostname, "cluster", "stop_node")
    print xml
    
def start_node(hostname):
    xml = send_ricci_command(hostname, "cluster", "start_node")
    print xml
    
def get_cluster_conf(hostname):
    xml = get_cluster_conf_xml(hostname)
    xml = minidom.parseString(xml).getElementsByTagName('cluster')[0].toprettyxml(indent='  ',newl='')
    print xml

def get_cluster_status(hostname):
    xml = send_ricci_command(hostname,"cluster","status")
    xml = minidom.parseString(xml).getElementsByTagName('cluster')[0].toprettyxml(indent='  ',newl='')
    print xml

def list_nodes(hostname):
    xml = get_cluster_conf_xml(hostname)
    dom = minidom.parseString(xml)
    for node in dom.getElementsByTagName('clusternode'):
        print node.getAttribute("name")

def list_services(hostname):
    xml = get_cluster_conf_xml(hostname)
    dom = minidom.parseString(xml)
    for node in dom.getElementsByTagName('service'):
        print_services_map(node,0)

def print_services_map(node,level):
    num_spaces = level * 2
    prefix = ""
    
    if node.nodeType == minidom.Node.TEXT_NODE:
        return
    for i in range(num_spaces):
        prefix = " " + prefix

    nodeattr = ""
    if node.attributes != None:
        length = node.attributes.length
        for i in range(length):
            nodeattr = nodeattr + node.attributes.item(i).value


    print prefix + node.tagName + ": " + nodeattr
    for cn in node.childNodes:
        print_services_map(cn, level + 1)

def list_domains(hostname):
    xml = get_cluster_conf_xml(hostname)
    dom = minidom.parseString(xml)
    for node in dom.getElementsByTagName('failoverdomain'):
        print node.getAttribute("name")

# Add a node to the cluster.conf
#   Before adding a node we need to verify another node
#   with the same name doesn't already exist
def add_node(hostname, node_to_add):
    nodeid_list = set()

    dom = minidom.parseString(get_cluster_conf_xml(hostname))
    for node in dom.getElementsByTagName('clusternode'):
        if (node.getAttribute("name") == node_to_add):
            print "Node '%s' already exists in cluster.conf" % node_to_add
            sys.exit(1)
        nodeid_list.update(node.getAttribute("nodeid"))
    node = dom.createElement("clusternode")
    node.setAttribute("name",node_to_add)

    # Use the first nodeid above 0 that isn't already used
    nodeid = 0
    while (True):
        nodeid = nodeid + 1
        if (str(nodeid) not in nodeid_list): break

    node.setAttribute("nodeid",str(nodeid))
    node.setAttribute("votes","1")
    dom.getElementsByTagName("clusternodes")[0].appendChild(node)
    set_cluster_conf(hostname,dom.toxml())
    print "Node %s added." % (node_to_add)

def remove_node(hostname, node_to_remove):
    nodeFound = False

    dom = minidom.parseString(get_cluster_conf_xml(hostname))
    for node in dom.getElementsByTagName('clusternode'):
        if (node.getAttribute("name") == node_to_remove):
            node.parentNode.removeChild(node)
            nodeFound = True

    if (nodeFound == False):
        print "Unable to find node %s" % node_to_remove
        sys.exit(1)

    set_cluster_conf(hostname,dom.toxml())

def get_version(hostname):
    dom = minidom.parseString(get_cluster_conf_xml(hostname))
    return dom.getElementsByTagName('cluster')[0].getAttribute("config_version")

def set_version(hostname, version):
    dom = minidom.parseString(get_cluster_conf_xml(hostname))
    dom.getElementsByTagName('cluster')[0].setAttribute("config_version",version)
    set_cluster_conf(hostname,dom.toxml(), False)

def increment_version(hostname):
    new_version = int(get_version(hostname)) + 1
    set_version(hostname,str(new_version))
    print new_version

def get_cluster_conf_xml(hostname):
    xml = send_ricci_command(hostname, "cluster", "get_cluster.conf")
    dom = minidom.parseString(xml)
    if dom.getElementsByTagName('cluster').length > 0:
      return dom.getElementsByTagName('cluster')[0].toxml()
    else:
      return empty_cluster_conf()

# Create a minimal cluster.conf file similiar to the one
# created by system-config-cluster
def empty_cluster_conf(name="cluster"):
    impl = minidom.getDOMImplementation()
    newdoc = impl.createDocument(None, "cluster", None)

    top = newdoc.documentElement
    top.setAttribute('config_version','1')
    top.setAttribute('name',name)
    fence_daemon = newdoc.createElement("fence_daemon")
    fence_daemon.setAttribute('post_fail_delay','0')
    fence_daemon.setAttribute('post_join_delay','3')
    clusternodes = newdoc.createElement("clusternodes")
    cman = newdoc.createElement("cman")
    fencedevices = newdoc.createElement("fencedevices")
    rm = newdoc.createElement("rm")
    failoverdomains = newdoc.createElement("failoverdomains")
    resources = newdoc.createElement("resources")
    
    top.appendChild(fence_daemon)
    top.appendChild(clusternodes)
    top.appendChild(cman)
    top.appendChild(fencedevices)
    rm.appendChild(failoverdomains)
    rm.appendChild(resources)
    top.appendChild(rm)

    return newdoc.toprettyxml()

def create_cluster(hostname, clustername):
    xml = empty_cluster_conf(clustername)
    set_cluster_conf(hostname,xml)

def add_method(hostname, method, options):
    method_found = False
    node_found = False

    if len(options) != 1:
        usage()
        sys.exit(2)

    nodename = options[0]

    dom = minidom.parseString(get_cluster_conf_xml(hostname))
    for node in dom.getElementsByTagName('clusternode'):
        if (node.getAttribute("name") == nodename):
            node_found = True
            for methodnode in node.getElementsByTagName("method"):
                if methodnode.getAttribute("name") == method:
                    method_found = True
                    break
            break

    if node_found == False:
        print "Node '%s' does not currently exist in cluster.conf." % (nodename)
        sys.exit(1)

    if method_found == True:
        print "Method '%s' already exists in cluster.conf." % (method)
        sys.exit(1)

    fencenodes = node.getElementsByTagName("fence")
    if len(fencenodes) == 0:
        fencenode = dom.createElement("fence")
    else:
        fencenode = fencenodes[0]

    methodnode = dom.createElement("method")
    methodnode.setAttribute("name", method)
    fencenode.appendChild(methodnode)
    node.appendChild(fencenode)
    set_cluster_conf(hostname, dom.toxml())
    print "Method %s added to %s." % (method, nodename)

def remove_method(hostname, method, options):
    method_found = False
    node_found = False
    
    if len(options) != 1:
        usage()
        sys.exit(2)

    nodename = options[0]
    dom = minidom.parseString(get_cluster_conf_xml(hostname))
    for node in dom.getElementsByTagName('clusternode'):
        if (node.getAttribute("name") == nodename):
            node_found = True
            for methodnode in node.getElementsByTagName("method"):
                if methodnode.getAttribute("name") == method:
                    method_found = True
                    break
            break

    if node_found == False:
        print "Node %s does not exist in cluster.conf." % (nodename)
        sys.exit(1)
    if method_found == False:
        print "Method %s is not present for %s." % (method, nodename)
        sys.exit(1)

    methodnode.parentNode.removeChild(methodnode)
    set_cluster_conf(hostname, dom.toxml())
    print "Method %s removed from %s." % (method, nodename)

def add_fencedev(hostname, name, options):
    dom = minidom.parseString(get_cluster_conf_xml(hostname))

    # Verify fencedevices section exists in cluster.conf
    fencedevices = dom.getElementsByTagName('fencedevices')
    if len(fencedevices) == 0:
        dom.getElementsByTagName('cluster')[0].appendChild(dom.createElement("fencedevices"))
    elif len(fencedevices) > 1:
        print "Error: Too many fencedevices elements in cluster.conf"
        sys.exit(1)
    
    # Verify fence device with same name does not already exist
    for fencedev in dom.getElementsByTagName('fencedevice'):
        if fencedev.getAttribute("name") == name:
            print "Fence device '%s' already exists in cluster.conf." % name
            sys.exit(1)

    newfencedev = dom.createElement("fencedevice")
    for option in options:
        (attr, sep, val) = option.partition('=')
        if (sep == ""):
            print "Invalid option: %s" % option
            sys.exit(1)
        newfencedev.setAttribute(attr,val)

    newfencedev.setAttribute("name", name)
    fencedevelem = dom.getElementsByTagName('fencedevices')[0]
    fencedevelem.appendChild(newfencedev)
    set_cluster_conf(hostname, dom.toxml())

def remove_fencedev(hostname, name):
    fencedev_found = False
    dom = minidom.parseString(get_cluster_conf_xml(hostname))

    # Verify fence device exists before attempting to remove
    for fencedev in dom.getElementsByTagName('fencedevice'):
        if fencedev.getAttribute("name") == name:
            fencedev.parentNode.removeChild(fencedev)
            fencedev_found = True

    if fencedev_found == False:
        print "Fence device '%s' does not exist in cluster.conf." % name
        sys.exit(1)

    set_cluster_conf(hostname, dom.toxml())

def add_fenceinst(hostname, name, options):
    fencedev_found = method_found = False

    if len(options) < 2:
        usage()
        sys.exit(2)
        
    nodename = options[0]
    methodname = options[1]
    dom = minidom.parseString(get_cluster_conf_xml(hostname))

    # Verify fence device exists
    for fencedev in dom.getElementsByTagName('fencedevice'):
        if fencedev.getAttribute("name") == name:
            fencedev_found = True
            break
    
    # Verify method exists for specified node
    for node in dom.getElementsByTagName('clusternode'):
        if node.getAttribute("name") == nodename:
            for method in node.getElementsByTagName('method'):
                if method.getAttribute("name") == methodname:
                    method_found = True
                    break
            break 

    if fencedev_found == False:
        print "Fence device '%s' not found." % name
        sys.exit(1)

    if method_found == False:
        print "Method '%s' not found in node '%s'." % (methodname, nodename)
        sys.exit(1)

    newfenceinst = dom.createElement("device")
    for option in options[2:]:
        (attr, sep, val) = option.partition('=')
        if (sep == ""):
            print "Invalid option: %s" % option
            sys.exit(1)
        newfenceinst.setAttribute(attr,val)

    newfenceinst.setAttribute("name", name)
    method.appendChild(newfenceinst)
    set_cluster_conf(hostname, dom.toxml())
    
def remove_fenceinst(hostname, name, options):
    fenceinst_found = False

    if len(options) < 2:
        usage()
        sys.exit(2)
        
    nodename = options[0]
    methodname = options[1]
    dom = minidom.parseString(get_cluster_conf_xml(hostname))

    # Verify fence instance exists before attempting to remove
    for node in dom.getElementsByTagName('clusternode'):
        if node.getAttribute("name") == nodename:
            for method in node.getElementsByTagName('method'):
                if method.getAttribute("name") == methodname:
                    for instance in method.getElementsByTagName('device'):
                        if instance.getAttribute("name") == name:
                            instance.parentNode.removeChild(instance)
                            fenceinst_found = True


    if fenceinst_found == False:
        print "Fence instance '%s' for node '%s' in method '%s' does not exist in cluster.conf." % (name, nodename, methodname)
        sys.exit(1)

    set_cluster_conf(hostname, dom.toxml())

def add_failoverdomain(hostname, name, options):
    dom = minidom.parseString(get_cluster_conf_xml(hostname))

    failoverdomains_array = dom.getElementsByTagName("failoverdomains")

    # Verify failoverdomains and rm exist in cluster.conf file
    if len(failoverdomains_array) > 0:
        failoverdomains = failoverdomains_array[0]
    else:
        rm_array = dom.getElementsByTagName("rm")
        if len(rm_array) == 0:
            rm = dom.getElementsByTagName("cluster")[0].appendChild(dom.createElement("rm"));
        else:
            rm = rm_array[0]
        failoverdomains = rm.appendChild(dom.createElement("failoverdomains"))

    # Verify that there already isn't a failover domain with the same name
    failoverdomain_found = False
    for failoverdomain in failoverdomains.getElementsByTagName("failoverdomain"):
        if failoverdomain.getAttribute("name") == name:
            failoverdomain_found = True
            break
    
    if failoverdomain_found:
        print "Failover domain '%s' already exists." % (name)
        sys.exit(1)
    
    failoverdomain = failoverdomains.appendChild(dom.createElement("failoverdomain"))
    failoverdomain.setAttribute("name",name)

    if "restricted" in options: failoverdomain.setAttribute("restricted", "1")
    else: failoverdomain.setAttribute("restricted", "0")
    if "ordered" in options: failoverdomain.setAttribute("ordered", "1")
    else: failoverdomain.setAttribute("ordered", "0")
    if "nofailback" in options: failoverdomain.setAttribute("nofailback", "1")
    else: failoverdomain.setAttribute("nofailback", "0")

    set_cluster_conf(hostname, dom.toxml())

def remove_failoverdomain(hostname, name):
    dom = minidom.parseString(get_cluster_conf_xml(hostname))

    failoverdomains = dom.getElementsByTagName("failoverdomains")
    if len(failoverdomains) > 0:
        for failoverdomain in failoverdomains[0].getElementsByTagName("failoverdomain"):
            if failoverdomain.getAttribute("name") == name:
                failoverdomains[0].removeChild(failoverdomain)
                set_cluster_conf(hostname, dom.toxml())
                return
    else:
        print "No failoverdomains section found in cluster.conf"
        sys.exit(1)

    print "Unable to find failover domain '%s' in cluster.conf file." % (name)
    sys.exit(1)
    
def ls_fencedev():
    rng = open(CLUSTERRNG)
    dom = minidom.parseString(rng.read())
    for elem in dom.getElementsByTagName("group"):
        if elem.getAttribute("rha:fence_agent"):
            print elem.getAttribute("rha:fence_agent")

def ls_fenceinst(fencedev):
    rng = open(CLUSTERRNG)
    dom = minidom.parseString(rng.read())
    for elem in dom.getElementsByTagName("group"):
        if elem.getAttribute("rha:fence_agent") == fencedev:
            for attr in elem.getElementsByTagName("attribute"):
                attrname = attr.getAttribute("name")
                invisible_attrs = ["verbose", "debug", "version", "help",
                        "option", "action", "separator"]
                if attrname not in invisible_attrs:
                    print attr.getAttribute("name") + " - " + attr.getAttribute("rha:description")

def add_service(hostname, name, options):
    dom = minidom.parseString(get_cluster_conf_xml(hostname))

    # Verify rm section exists in cluster.conf
    rm_array = dom.getElementsByTagName("rm")
    if len(rm_array) == 0:
        rm = dom.getElementsByTagName("cluster")[0].appendChild(dom.createElement("rm"));
    else:
        rm = rm_array[0]

    # Verify service doesn't exist with the same name
    for service in dom.getElementsByTagName('service'):
        if service.getAttribute("name") == name:
            print "Service '%s' already exists in cluster.conf." % name
            sys.exit(1)

    service = dom.getElementsByTagName('rm')[0].appendChild(dom.createElement("service"))
    for option in options:
        (attr, sep, val) = option.partition('=')
        if (sep == ""):
            print "Invalid option: %s" % option
            sys.exit(1)
        service.setAttribute(attr,val)

    service.setAttribute("name", name)
    set_cluster_conf(hostname, dom.toxml())

def add_subservice(hostname, name, options):
    dom = minidom.parseString(get_cluster_conf_xml(hostname))
    serviceFound = False

    # Verify top level service exists
    for service in dom.getElementsByTagName("service"):
        if service.getAttribute("name") == name:
            serviceFound = True
            break;

    if serviceFound == False:
        print "Unable to find service: %s" % name
        sys.exit(1)

    subservice_type = options.pop(0)
    subservice = service.appendChild(dom.createElement(subservice_type))
    for option in options:
        (attr, sep, val) = option.partition('=')
        if (sep == ""):
            print "Invalid option: %s" % option
            sys.exit(1)
        subservice.setAttribute(attr,val)
    set_cluster_conf(hostname, dom.toxml())

# Set the cluster.conf file and increment the version
# If global variable propagate is true, propagate to entire cluster
def set_cluster_conf(hostname, xml, increment = True):
    dom = minidom.parseString(xml)

    if increment:
      version = dom.getElementsByTagName("cluster")[0].getAttribute("config_version")
      version = int(version) + 1
      dom.getElementsByTagName("cluster")[0].setAttribute("config_version",str(version))
      xml = dom.toxml()

    xml = xml.replace('<?xml version="1.0" ?>','')
    log_msg (xml)

    if propagate:
      log_msg (send_ricci_command(hostname, "cluster", "set_cluster.conf", ("cluster.conf","xml","",xml), ("propagate", "boolean", "true")))
    else:
      log_msg (send_ricci_command(hostname, "cluster", "set_cluster.conf", ("cluster.conf","xml","",xml)))


def send_ricci_command(hostname, module, command, *vars):
    global password
    variables = ""

    for value in vars:
        variables = variables + '<var mutable="false" name="%s" type="%s" value="%s">' % (value[0],value[1],value[2])
        if (len(value) > 3):
            variables = variables + value[3]
        variables = variables + "</var>"

    # If a password is set, then we authenticate
    if password != None:
        msg = '<ricci function="authenticate" password="%s" version="1.0"/>' % password
        res = send_to_ricci(hostname, msg)     
        dom = minidom.parseString(res[1])
        ricci_elem = dom.getElementsByTagName('ricci')
        if (ricci_elem[0].getAttribute("authenticated") != "true"): 
            print "Unable to authenticate with ricci node, please check root password."
            sys.exit(1)
    
    msg = '<ricci function="process_batch" async="false" version="1.0"><batch><module name="%s"><request API_version="1.0"><function_call name="%s">%s</function_call></request></module></batch></ricci>' % (module,command,variables)
    res = send_to_ricci(hostname, msg)
    dom = minidom.parseString(res[1].replace('\t',''))
    xml = dom.getElementsByTagName('function_response')[0].toxml()
    return xml 

def send_to_ricci(hostname, msg):
    cert = os.path.expanduser("~/.ricci/cacert.pem")
    key = os.path.expanduser("~/.ricci/privkey.pem")
    config = os.path.expanduser("~/.ricci/cacert.config")
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # Make sure we have a client certificate and private key
    # If not we need to autogenerate them (including creating an
    # openssl configuration file
    if (os.path.isfile(cert) == False or os.path.isfile(key) == False):
        print "Autogenerating private key and certificate."
        if not os.path.exists(os.path.expanduser("~/.ricci")):
            os.mkdir(os.path.expanduser("~/.ricci"),0700);
        f = open (config, 'w')
        f.write("""
      [ req ]
      distinguished_name     = req_distinguished_name
      attributes             = req_attributes
      prompt                 = no

      [ req_distinguished_name ]
      C                      = US
      ST                     = State or Province
      L                      = Locality
      O                      = Organization Name
      OU                     = Organizational Unit Name
      CN                     = Common Name
      emailAddress           = root@localhost

      [ req_attributes ]
""")
        f.close()
        os.system ("/usr/bin/openssl genrsa -out %s 2048" % key)
        os.system ("/usr/bin/openssl req -new -x509 -key %s -out %s -days 1825 -config ~/.ricci/cacert.config" % (key,cert))

    ss = ssl.wrap_socket(s, key, cert)
    try:
        ss.connect((hostname, RICCI_PORT))
    except socket.error:
        print "Unable to connect to %s, make sure the ricci server is started." % hostname
        sys.exit(1)

    log_msg ("***Sending to ricci server:")
    log_msg (msg)
    log_msg ("***Sending End")
    logging.debug("Connected...")
    res1 = ss.read(1024)
    logging.debug("Writing...")
    logging.debug(msg)
    ss.write(msg)
    logging.debug("Writen...")
    res2 = ''
    while True:
        logging.debug("Waiting to read...")
        buff = ss.read(10485760)
        logging.debug(buff)
        logging.debug("Read...")
        if buff == '':
            break
        res2 += buff
        try:
            minidom.parseString(res2)
            break
        except:
            pass
    log_msg ("***Received from ricci server")
    log_msg (res2)
    log_msg ("***Receive End")
    return res1, res2

def log_msg(message):
    global debug

    if debug == True:
      print message

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