| #!/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. |
| |
| ''' |
| USAGE: gp_df [-m] |
| platform independent df command |
| where -m will display output in megabytes |
| ''' |
| |
| import os, re, sys, time, subprocess |
| |
| try: |
| from optparse import Option, OptionParser |
| from gppylib.gpparseopts import OptParser, OptChecker |
| from gppylib.commands.unix import SYSTEM |
| except ImportError, e: |
| sys.exit('Cannot import modules. Please check that you have sourced greenplum_path.sh. Detail: ' + str(e)) |
| |
| class BytesFormatter: |
| BYTES = 1 |
| KILOBYTES = 2 |
| MEGABYTES = 3 |
| |
| |
| class FileSystem: |
| def __init__(self, device, dir, type): |
| self.device = device |
| self.dir = dir |
| self.type = type |
| self.total_bytes = 0 |
| self.used_bytes = 0 |
| self.available_bytes = 0 |
| |
| @staticmethod |
| def PrintHeader(formatter): |
| if formatter == BytesFormatter.BYTES: |
| used = "USED_BYTES" |
| available = "AVAILABLE_BYTES" |
| elif formatter == BytesFormatter.KILOBYTES: |
| used = "USED_KB" |
| available = "AVAILABLE_KB" |
| elif formatter == BytesFormatter.MEGABYTES: |
| used = "USED_MB" |
| available = "AVAILABLE_MB" |
| else: |
| raise Exception("unknown bytes formatter") |
| |
| print "%s %s %s %s %s" % ("DEVICE", "DIR", "TYPE", used, available) |
| |
| def Print(self, formatter): |
| try: |
| if formatter == BytesFormatter.BYTES: |
| used = self.used_bytes |
| available = self.available_bytes |
| elif formatter == BytesFormatter.KILOBYTES: |
| used = int(self.used_bytes/1024) |
| available = int(self.available_bytes/1024) |
| elif formatter == BytesFormatter.MEGABYTES: |
| used = int(self.used_bytes/1024/1024) |
| available = int(self.available_bytes/1024/1024) |
| else: |
| raise Exception("unknown bytes formatter") |
| except Exception, e: |
| print >> sys.stderr, e.__str__() |
| print >> sys.stderr, "Error converting disk usage to numerical form" |
| sys.exit(1) |
| except: |
| print >> sys.stderr, "Error converting disk usage to numerical form" |
| sys.exit(1) |
| |
| print "%s %s %s %d %d" % (self.device, self.dir, self.type, used, available) |
| |
| def getLinuxDirectoryList(): |
| |
| interestedFSTypes = set(['xfs', 'ext3', 'ext4']) |
| |
| fsList = [] |
| try: |
| fd = open('/proc/mounts') |
| buffer = fd.read() |
| fd.close() |
| for line in buffer.splitlines(): |
| fields = line.split() |
| if len(fields) != 6: |
| raise Exception("Wrong number of fields in /proc/mounts entry: %s" % line.strip()) |
| if fields[2] not in interestedFSTypes: |
| continue |
| fsList.append(FileSystem(device=fields[0], dir=fields[1], type=fields[2])) |
| except Exception, e: |
| print >> sys.stderr, e.__str__() |
| print >> sys.stderr, "Error reading list of mounts" |
| sys.exit(1) |
| except: |
| print >> sys.stderr, "Error reading list of mounts" |
| sys.exit(1) |
| |
| return fsList |
| |
| |
| def getSolarisDirectoryList(): |
| |
| cmd = "zfs list -H -t filesystem -o name,mountpoint" |
| p = subprocess.Popen(cmd, shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE) |
| result = p.communicate() |
| errormsg = result[1].strip() |
| output = result[0] |
| if p.returncode: |
| print >> sys.stderr, errormsg |
| print >> sys.stderr, "error getting zpool information from host" |
| sys.exit(1) |
| |
| fsList = [] |
| for line in output.splitlines(): |
| fields = line.split() |
| if len(fields) != 2: |
| print >> sys.stderr, "bad output line from zfs list: %s" % line |
| continue |
| |
| # we want only zfs pools not filesystems that are a subset of a zfs pool |
| fsname = fields[0].strip() |
| mount = fields[1].strip() |
| if re.search("/", fsname): |
| continue |
| fsList.append(FileSystem(device=fsname, dir=mount, type='zfs')) |
| |
| return fsList |
| |
| |
| def getDirectoryList(): |
| |
| if SYSTEM.getName() == "linux": |
| return getLinuxDirectoryList() |
| elif SYSTEM.getName() == "sunos": |
| return getSolarisDirectoryList() |
| else: |
| print >> sys.stderr, "Unsupported platform" |
| sys.exit(1) |
| |
| |
| ###### main() |
| if __name__ == '__main__': |
| |
| gphome = os.environ.get('GPHOME') |
| if not gphome: |
| print "GPHOME not set" |
| sys.exit(1) |
| |
| parser = OptParser(option_class=OptChecker) |
| parser.remove_option('-h') |
| parser.add_option('-h', '-?', '--help', action='store_true') |
| parser.add_option('-m', '--megabytes', action='store_true') |
| (options, args) = parser.parse_args() |
| |
| if options.help: |
| print __doc__ |
| sys.exit(1) |
| |
| fsList = getDirectoryList() |
| |
| for fs in fsList: |
| stats = os.statvfs(fs.dir) |
| fs.total_bytes = stats.f_frsize * stats.f_blocks |
| fs.available_bytes = stats.f_frsize * stats.f_bfree |
| fs.used_bytes = fs.total_bytes - fs.available_bytes |
| |
| if fs.used_bytes < 0: |
| print >> sys.stderr, "statvfs output for device=%s dir=%s has more free bytes than total bytes" % (fs.device, fs.dir) |
| print >> sys.stderr, stats |
| sys.exit(1) |
| |
| if options.megabytes: |
| formatter = BytesFormatter.MEGABYTES |
| else: |
| formatter = BytesFormatter.BYTES |
| |
| FileSystem.PrintHeader(formatter) |
| for fs in fsList: |
| fs.Print(formatter) |
| |
| |