#!/usr/bin/env python
# vim: set expandtab ts=4 sw=4:

# Copyright (C) 2009 University of Victoria
# You may distribute under the terms of either the GNU General Public
# License or the Apache v2 License, as specified in the README file.

# cloud_status - tool to display information about cloud scheduler
# 
import xmlrpclib
import sys
import socket
from optparse import OptionParser
import logging
import platform

import cloudscheduler.utilities as utilities 
log = utilities.get_cloudscheduler_logger()

import cloudscheduler.cloud_management as cloud_management
import cloudscheduler.config as config

def main(argv=None):

    # Parse command line options
    parser = OptionParser()
    parser.add_option("-f", "--config-file", dest="config_file", metavar="FILE",
                      help="Designate a Cloud Sceduler config file")
    parser.add_option("-s", "--server-hostname", dest="server_hostname",
                      metavar="HOSTNAME",
                      help="Pick a specific machine's Cloud Scheduler"
                           "information server")
    parser.add_option("-p", "--port", dest="port", metavar="PORT",
                      help="Pick a custom port to connect to Cloud Scheduler"
                           "information server")
    parser.add_option("-a", "--all-cluster", action="store_true", 
                      dest="all_cluster", default=False, 
                      help="Get All clusters in Cloud Scheduler, and displays remaining resources")
    parser.add_option("-c", "--cluster", dest="cluster_name", metavar="NAME", 
                      help="Get Information on a cluster")
    parser.add_option("-m", "--virtual-machines",action="store_true", 
                      dest="vms", default=False, 
                      help="Get all VMs in Cloud Scheduler")
    parser.add_option("-n", "--vm-info", dest="vm_id", metavar="ID", 
                      help="Get information on a virtual machine")
    parser.add_option("-j", "--json", dest="json", action="store_true",
                      default=False, help="Get JSON output")
    parser.add_option("-d", "--developer-information", action="store_true",
                      dest="dev_info", default=False,
                      help="Show developer information about cloud_scheduler")
    parser.add_option("-q", "--job-queue", metavar="QUEUE",
                      action="store", dest="job_queue",
                      type="choice", choices=['all', 'new', 'sched', 'high', 'running', 'idle', 'held', 'complete'],
                      help="Get Information about the job queues. [all, new, sched, high, running, idle, held, complete]")
    parser.add_option("-i", "--ip-address", default=False, action="store_true",
                      dest="ips",
                      help="output ip information for munin monitoring")
    parser.add_option("-b", "--boot-time", dest="boot_time",
                      action="store_true", default=False, help="Display boot times")
    parser.add_option("-t", "--diff_type", dest="diff_type",
                      action="store_true", default=False, help="Display diff_types for debugging")
    parser.add_option("-g", "--avg_job_time", dest="get_job_run_times", action="store_true",
                      default=False, help="Display Average Run time of Jobs on VMs")
    parser.add_option("-l", "--cloud-conf", dest='cloud_conf', action="store_true",
                      default=False, help='Display the cloud_resources config')
    parser.add_option("-o", "--total-vms", dest="totals", action="store_true", default=False,
                      help="Output the total VMs in CloudScheduler or on a cloud(-c)")
    parser.add_option("-u", "--vm-status", dest="status", action="store_true", default=False,
                      help="Condensed VM Status information, use -c to limit to single cloud.")
    parser.add_option("-r", "--missing-vms", dest="missing_vms", action="store_true", default=False,
                      help="Print a list of Condor class ads CS has no matching VM for.")
    parser.add_option("-x", "--heart-beats", dest="heart_beats", action="store_true", default=False,
                      help="Print thread heart beat times since thread last completed cycle.")
    parser.add_option("-z", "--boot-failures", dest="boot_failures", action="store_true", default=False,
                      help="Print list of reasons jobs have not booted a VM.")
    parser.add_option("-w", "--image-failures", dest="image_failures", action="store_true", default=False,
                      help="Print list of images failing to properly boot.")

    (cli_options, args) = parser.parse_args()

    # Initialize config
    if cli_options.config_file:
        config.setup(cli_options.config_file)
    else:
        config.setup()


    # Get port to connect to info server.
    #   Precedence: -p argument, then from config module
    if cli_options.port:
        server_port = cli_options.port
    else:
        server_port = config.info_server_port

    if cli_options.server_hostname:
        server_hostname = cli_options.server_hostname
    else:
        server_hostname = platform.node()

    # Connect to info server
    try:
        s = xmlrpclib.ServerProxy("http://%s:%s" %
                                  (server_hostname, server_port))
        if cli_options.all_cluster and not cli_options.json:
            print s.get_cluster_resources()
        elif cli_options.vms:
            print s.get_cluster_vm_resources()
        elif cli_options.status:
            if cli_options.cluster_name:
                print s.get_vm_stats(cli_options.cluster_name)
            else:
                print s.get_vm_stats()
        elif not cli_options.json and cli_options.vm_id and cli_options.cluster_name:
            print s.get_vm_info(cli_options.cluster_name, cli_options.vm_id)
        elif cli_options.vm_id and not cli_options.cluster_name:
            print "Please provide -c cluster_name with vm ID"
        elif not cli_options.json and cli_options.cluster_name and not cli_options.vm_id and not cli_options.totals:
            print s.get_cluster_info(cli_options.cluster_name)
        elif cli_options.json and cli_options.all_cluster:
            print s.get_json_resource()
        elif cli_options.json and cli_options.vm_id and cli_options.cluster_name:
            print s.get_json_vm(cli_options.cluster_name, cli_options.vm_id)
        elif cli_options.json and cli_options.cluster_name and not cli_options.vm_id:
            print s.get_json_cluster(cli_options.cluster_name)
        elif (cli_options.dev_info):
            print s.get_developer_information()
        elif cli_options.job_queue:
            if cli_options.job_queue.startswith('a'):
                print "Jobs in Scheduled Queue"
                print s.get_schedjobs()
                print "Jobs in New Queue"
                print s.get_newjobs()
                print "Jobs in High Priority Queue"
                print s.get_highjobs()
            elif cli_options.job_queue.startswith('n'):
                print "Jobs in New Queue"
                print s.get_newjobs()
            elif cli_options.job_queue.startswith('s'):
                print "Jobs in Scheduled Queue"
                print s.get_schedjobs()
            elif cli_options.job_queue.startswith('hi'):
                print "Jobs in High Priority Queue"
                print s.get_highjobs()
            elif cli_options.job_queue.startswith('he'):
                print "Jobs in Held state"
                print s.get_heldjobs()
            elif cli_options.job_queue.startswith('i'):
                print "Jobs in Idle state"
                print s.get_idlejobs()
            elif cli_options.job_queue.startswith('c'):
                print "Jobs in Complete state"
                print s.get_completejobs()
            elif cli_options.job_queue.startswith('r'):
                print "Jobs in Running state"
                print s.get_runningjobs()
        elif cli_options.ips:
            print s.get_ips_munin()
        elif cli_options.boot_time:
            print s.get_vm_startup_time()
        elif cli_options.diff_type:
            print s.get_diff_types()
        elif cli_options.get_job_run_times:
            print s.get_vm_job_run_times()
        elif cli_options.cloud_conf:
            print s.get_cloud_config_values()
        elif cli_options.totals and cli_options.cluster_name:
            print s.get_total_vms_cloud(cli_options.cluster_name)
        elif cli_options.totals:
            print s.get_total_vms()
        elif cli_options.missing_vms:
            print s.get_missing_vm_list()
        elif cli_options.heart_beats:
            print s.get_thread_heart_beats()
        elif cli_options.boot_failures:
            print s.get_job_failure_reasons()
        elif cli_options.image_failures:
            print s.get_image_failures()
        else:
            print s.get_cloud_resources()

    except socket.error:
        print "%s: couldn't connect to cloud scheduler at %s on port %s."\
               % (sys.argv[0], server_hostname, server_port)
        print "Is the cloud scheduler running on port %s?" % server_port
        return 1
    except:
        print "Unexpected error: ", sys.exc_info()[0], sys.exc_info()[1]
        print "Is the cloud scheduler running on port %s?" % server_port
        return 1

    return 0


if __name__ == "__main__":
    sys.exit(main())
