| #! /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. |
| # ----------------------------------------------------------------------- |
| |
| # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| # + |
| # + ducc_disk_info |
| # + |
| # + purpose: report on DUCC_HOME disk usage |
| # + |
| # + input: none (DUCC_HOME implied from location of this script) |
| # + |
| # + output: filesystem=<i>% quota=<j>% |
| # + |
| # + exit code: the greater of { i, j } |
| # + |
| # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |
| import os |
| import subprocess |
| import sys |
| |
| from optparse import HelpFormatter |
| from optparse import OptionGroup |
| from optparse import OptionParser |
| |
| # ---------------------------------------------- |
| |
| # Extend OptionParser class |
| class ExtendedOptionParser(OptionParser): |
| # override epilog formatter so |
| # that newlines are not deleted! |
| def format_epilog(self, formatter): |
| return self.epilog |
| |
| # ---------------------------------------------- |
| |
| cmd_df = 'df' |
| cmd_quota = 'quota' |
| |
| code = -1 |
| message = 'DUCC_HOME: ' |
| |
| # epilog for --help |
| def get_epilog(): |
| epilog = '' |
| epilog = epilog + '\n' |
| epilog = epilog+'Purpose: display the filesystem and quota usage for the DUCC_HOME directory relative to the location of this script.' |
| epilog = epilog + '\n' |
| return epilog |
| |
| # 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('--code', action='store_true', dest='flag_code', default=False, |
| help='display exit code, which is the greater of disk usage percentage and quota usage percentage') |
| parser.add_option('--debug', action='store_true', dest='flag_debug', default=False, |
| help='display debug information') |
| parser.add_option('--nomsg', action='store_false', dest='flag_msg', default=True, |
| help='suppress display of filesystem and quota percentages used message') |
| (options, args) = parser.parse_args() |
| |
| # normalize path to always end with / |
| def normalize_path(path): |
| retVal = path |
| if(not path.endswith('/')): |
| retVal = path+'/' |
| return retVal |
| |
| # normalize quota value to bytes |
| def normalize_quota(value): |
| if(value.endswith('M')): |
| tval = value.split('M')[0] |
| retVal = int(tval)*1024*1024 |
| elif(value.endswith('k')): |
| tval = value.split('k')[0] |
| retVal = int(tval)*1024 |
| else: |
| retVal = int(value) |
| return retVal |
| |
| # determine quota usage |
| def check_quota(): |
| global code |
| global cmd_quota |
| global message |
| global filesystem |
| try: |
| p = subprocess.Popen([cmd_quota, '-A'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| out, err = p.communicate() |
| qfs = None |
| data = None |
| fs1 = normalize_path(filesystem) |
| #print fs1 |
| for line in out.splitlines(): |
| tokens = line.split() |
| #print tokens |
| if(qfs == None): |
| fs2 = normalize_path(tokens[0]) |
| #print fs2 |
| if(fs1 == fs2): |
| qfs = fs1 |
| elif(data == None): |
| data = tokens |
| break |
| blocks = normalize_quota(data[0]) |
| limit = normalize_quota(data[2]) |
| qpct = int(blocks/(limit*1.0)*100) |
| #print qfs, blocks, limit, qpct |
| message = message+'quota='+str(qpct)+'%'+' ' |
| except Exception,e: |
| emessage = 'Exception: '+str(e) |
| emessage = emessage.strip() |
| if(options.flag_debug): |
| print emessage |
| message = message+'quota='+'N/A'+' ' |
| return |
| |
| # determine filesystem usage |
| def check_disk(): |
| global ducc_home |
| global code |
| global cmd_df |
| global message |
| global filesystem |
| try: |
| p = subprocess.Popen([cmd_df, ducc_home], stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| out, err = p.communicate() |
| pctused = 0 |
| for line in out.splitlines(): |
| tokens = line.split() |
| filesystem = tokens[0].strip() |
| pctused = tokens[4].split('%')[0] |
| number = float(pctused) |
| if(pctused > code): |
| code = pctused |
| message = message+'filesystem='+pctused+'%'+' ' |
| except Exception,e: |
| emessage = 'Exception: '+str(e) |
| emessage = emessage.strip() |
| if(options.flag_debug): |
| print emessage |
| message = message+'filesystem='+'N/A'+' ' |
| return |
| |
| # process |
| def process(): |
| check_disk() |
| check_quota() |
| return |
| |
| # initialize |
| def initialize(): |
| global ducc_home |
| pathname = os.path.dirname(sys.argv[0]) |
| ducc_home = pathname.rsplit('/',2)[0] |
| parse_cmdline() |
| return |
| |
| # main |
| def main(argv): |
| global ducc_home |
| global message |
| global code |
| try: |
| initialize() |
| process() |
| except Exception,e: |
| message = 'Exception: '+str(e) |
| message = message.strip() |
| if(options.flag_msg): |
| print message |
| if(options.flag_code): |
| sys.exit(code) |
| |
| if __name__ == '__main__': |
| main(sys.argv[1:]) |