#! /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 datetime import getpass import socket import sys import time from HTMLParser import HTMLParser from optparse import HelpFormatter from optparse import OptionGroup from optparse import OptionParser default_host = 'localhost' default_port = '42133' protocol = 'http://' servlet = '/ducc-servlet/classic-jobs-data' options = None sep = '\n' found = False # ---------------------------------------------- # Extend OptionParser class class ExtendedOptionParser(OptionParser): # override epilog formatter so # that newlines are not deleted! def format_epilog(self, formatter): return self.epilog # ---------------------------------------------- # parser for the jobs WS page class DuccHtmlParser(HTMLParser): token = 0 id = '' date = '' duration= '' user = '' sched_class ='' state = '' reason = '' services = '' processes = '' init_fails = '' run_fails = '' pgin = '' swap = '' memory = '' total = '' done = '' error = '' dispatch = '' retry = '' preempt = '' description = '' def handle_starttag(self, tag, attrs): if(tag == 'tr' ): self.token = 0 elif(tag == 'td' ): self.token = self.token + 1 elif(tag == 'span' ): pass elif(tag == 'input' ): pass elif(tag == 'a' ): pass elif(tag == 'br' ): pass elif(tag == 'div' ): pass elif(tag == 'i' ): pass else: debug("start: "+tag) def handle_endtag(self, tag): global sep global options global found if(options.id == self.id): if(tag == 'tr' ): found = True text = '' \ +'id............ '+self.id \ +sep \ +'date.......... '+self.date \ +sep \ +'duration...... '+self.duration \ +sep \ +'user.......... '+self.user \ +sep \ +'class......... '+self.sched_class \ +sep \ +'state......... '+self.state \ +sep \ +'reason........ '+self.reason \ +sep \ +'services...... '+self.services \ +sep \ +'processes..... '+self.processes \ +sep \ +'init_fails.... '+self.init_fails \ +sep \ +'run_fails..... '+self.run_fails \ +sep \ +'pgin.......... '+self.pgin \ +sep \ +'swap.......... '+self.swap \ +sep \ +'memory........ '+self.memory \ +sep \ +'total......... '+self.total \ +sep \ +'done.......... '+self.done \ +sep \ +'error......... '+self.error \ +sep \ +'dispatch...... '+self.dispatch \ +sep \ +'retry......... '+self.retry \ +sep \ +'preempt....... '+self.preempt \ +sep \ +'description... '+self.description \ +'' print text elif(tag == 'td' ): pass elif(tag == 'span' ): pass elif(tag == 'input' ): pass elif(tag == 'a' ): pass elif(tag == 'br' ): pass elif(tag == 'div' ): pass elif(tag == 'i' ): pass else: debug("end: "+tag) def handle_data(self, data): global options if(self.token == 0): pass elif(self.token == 1): pass # Id elif(self.token == 2): self.id = data if(options.id == self.id): # Start if(self.token == 3): self.date = data # Duration elif(self.token == 4): self.duration = self.duration+data elif(self.token == 5): self.user = data elif(self.token == 6): self.sched_class = data elif(self.token == 7): self.state = data elif(self.token == 8): self.reason = data elif(self.token == 9): self.services = data elif(self.token == 10): self.processes = data elif(self.token == 11): self.init_fails = data elif(self.token == 12): self.run_fails = data elif(self.token == 13): self.pgin = data elif(self.token == 14): self.swap = data elif(self.token == 15): self.memory = data elif(self.token == 16): self.total = data elif(self.token == 17): self.done = data elif(self.token == 18): self.error = data elif(self.token == 19): self.dispatch = data elif(self.token == 20): self.retry = data elif(self.token == 21): self.preempt = data elif(self.token == 22): self.description = data else: debug("token: "+str(self.token)+" "+"data: "+data) # ----------------------------------------------------------------------- # epilog for --help def get_epilog(): epilog = '' return epilog # produce a time stamp def get_timestamp(): tod = time.time() timestamp = datetime.datetime.fromtimestamp(tod).strftime('%Y-%m-%d %H:%M:%S') return timestamp # to console def to_stdout(text): try: print text except: pass try: sys.stdout.flush() except: pass def close(): try: sys.stdout.close() except: pass # check for log-style formating of text message def is_log_format(): retVal = False try: if(not options == None): if(options.flag_log_format): retVal = True except Exception: pass return retVal # info message to log def info(text): prefix = '' if(is_log_format()): type = 'I' prefix = get_timestamp()+' '+type+' ' line = prefix+text to_stdout(line) # debug message def debug(text): global options if(not options == None): if(options.flag_debug): prefix = '' if(is_log_format()): type = 'D' prefix = get_timestamp()+' '+type+' ' line = prefix+text to_stdout(line) # error message def error(text): prefix = '' if(is_log_format()): type = 'E' prefix = get_timestamp()+' '+type+' ' line = prefix+text to_stdout(line) # exception def exception(e): to_stdout(str(e)) # id is required def validate_id(): global options if(not options.id): error('required "id" not specified') exit(1) # --target host:port of WS for fetching of daemons status def validate_target(): global options global default_host global default_port global protocol global servlet target = options.target if(':' not in target): target = target+':'+default_port if(target.startswith(protocol)): target = target.replace(protocol,'',1) options.ducc_url_base = protocol+target options.ducc_url_servlet = protocol+target+servlet debug('target: '+options.ducc_url_base) # parse command line def parse_cmdline(): global options parser = ExtendedOptionParser(epilog=get_epilog()) width = 45 parser.formatter.help_position = width parser.formatter.max_help_position = width parser.add_option('--id', action='store', dest='id', default=None, help='[REQUIRED] id of job to query') parser.add_option('--debug', action='store', dest='flag_debug', default=False, help='display debugging information') parser.add_option('--target', action='store', dest='target', default=default_host+':'+default_port, help=': with default of '+default_host+':'+default_port) (options, args) = parser.parse_args() # -id validate_id() # -target validate_target() # fetch current daemons state def fetch_state_current(): global options import urllib2 try: opener = urllib2.build_opener() response = opener.open(options.ducc_url_servlet) options.ducc_raw_data = response.read() debug(options.ducc_raw_data) except Exception,e: error('unable to fetch data from '+options.ducc_url_servlet) exception(e) exit(1) # transform raw data def transform(): global options global head_daemons global found try: parser = DuccHtmlParser() parser.feed(options.ducc_raw_data) if(found == False): print options.id+' '+'not found' except Exception,e: error('unable to transform data from '+options.ducc_url_servlet) exception(e) exit(1) def main(argv): global default_host try: from ducc_base import DuccBase base = DuccBase() default_host = base.ducc_properties.get('ducc.head') parse_cmdline() fetch_state_current() transform() except Exception,e: error('exception in main') exception(e) if __name__ == '__main__': main(sys.argv[1:])