#!/usr/bin/env python
# -----------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
# -----------------------------------------------------------------------


import os
import sys
import glob
import subprocess
import string
import binascii

from ducc_util  import DuccUtil

class DuccRmQOccupancy(DuccUtil):


    def format(self, nodes, shares):
        typemap = {'R':'Res', 'M':' AP', 'J':'Job', 'S':'Svc'}
        print("%20s %6s %11s %6s %10s %15s %10s %6s %6s %6s %8s %7s %10s %8s" %  ("Node", "Status", "Blacklisted", "Online", "Responsive", "Nodepool", "Memory", "Order", "Free", "In-Use", "Np-InUse", "Quantum", "Reservable", "Classes"))
        print("%20s %6s %11s %6s %10s %15s %10s %6s %6s %6s %8s %7s %10s %8s" %  ("----", "------", "-----------", "------", "----------", "--------", "------", "-----", "----", "------", "--------", "-------", "----------", "-------"))
        for n in nodes:
            if (n['blacklisted'] == 'False' and n['online'] == 'True' and n['responsive'] == 'True'):
                status = 'up'
            else:
                status = 'down'
            print "%20s %6s %11s %6s %10s %15s %10s %3s(Q) %6s %6s %8s %7s %10s  %-8s" %  (n['name'], status, n['blacklisted'], n['online'], n['responsive'], n['nodepool'], 
                                                                             n['memory'], n['share_order'], n['shares_left'], n['assignments'], 
                                                                             n['np_assignments'], n['quantum'], n['reservable'], n['classes'])
            if ( shares.has_key(n['name']) ):
                for s in shares[n['name']]:
                    type = typemap[s['jobtype']]
                    fmt = '%19s ' + type +':%-8s ShareId:%-8s Shares:%-s InitTime:%-8s Investment:%-8s Evicted:%-5s Purged:%-5s Fixed:%-5s State:%-10s'
                    state = s['state']
                    if ( state == 'null' ):
                        state = "Assigned"
                    print fmt %  ('', s['job_id'], s['ducc_dbid'], s['share_order'], s['init_time'], s['investment'], s['evicted'], s['purged'], s['fixed'], state)

                print ''


    def parse_header(self, header):
        ret = []
        parts = header.split('|')
        for p in parts:
            ret.append(p.strip())
        return ret

    def parse_node(self, header, line):
        parts = line.split('|')
        ret = {}
        for k, v in zip(header, parts):
            ret[k] = v.strip()
        return ret

    def parse_share(self, header, line):
        parts = line.split('|')
        ret = {}
        for k, v in zip(header, parts):
            ret[k] = v.strip()
        return ret


    def rmnodes(self, lines):
        nodes = []
        shares = {}
        header = []
        for l in lines:
            if ( l == '' ):
                continue
            if ( '---' in l ):
                continue;
            if ( 'rows)' in l ):
                continue;
            if ( 'assignments' in l ):
                doing_nodes = True
                doing_shares = False
                header = self.parse_header(l)
                continue
            if ( 'investment' in l ):
                doing_nodes = False
                doing_shares = True
                header = self.parse_header(l)
                continue
            if ( doing_nodes ):
                nodes.append(self.parse_node(header, l))
                continue
            if ( doing_shares ):
                s = self.parse_share(header, l)
                k = s['node']
                if ( shares.has_key(k) ):
                    share_list = shares[k]
                else:
                    share_list = []
                    shares[k] = share_list
                share_list.append(s)
                continue
        return nodes, shares
    
    def main(self, argv):

        if len(argv) > 0:
            print 'rm_qoccupancy queries and formats the current state of the RM scheduling tables. It takes no parameters.'
            sys.exit(1);

        DH = self.DUCC_HOME
        dbn = self.get_db_host()

        guest_pw = self.db_password_guest

        os.environ['TERM'] = 'dumb'      # insure no colors.  --no-color isn't inhibiting colors in this shell for some reason.
        CMD = [DH + '/cassandra-server/bin/cqlsh', dbn, '-u', 'guest', '-p', guest_pw, '-e', '"select * from ducc.rmnodes; select * from ducc.rmshares;"']
        CMD = ' '.join(CMD)

        lines = []
        proc = subprocess.Popen(CMD, bufsize=0, stdout=subprocess.PIPE, shell=True)
        for line in proc.stdout:
            # print line.strip()
            lines.append(line.strip())

        nodes, shares = self.rmnodes(lines)
        self.format(nodes, shares)


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

    
