#!/usr/bin/env python
# vsphere-datastores --- show datastore capacity and usage

# Author: Noah Friedman <friedman@splode.com>
# Created: 2018-03-30
# Public domain

# $Id: vsphere-datastores,v 1.11 2019/08/23 22:58:28 friedman Exp $

# Commentary:
# Code:

from   __future__ import print_function
from   pyVmomi    import vim
import vspherelib     as vsl
import re

props = [ 'summary.name',
          'summary.capacity',
          'summary.freeSpace',
          'summary.uncommitted' ]

def get_args():
    p = vsl.ArgumentParser( loadrc=True )
    p.add_bool( '-H', '--header', help='Show column headers' )
    p.add( 'pattern',  nargs='*', help='Datastore names or patterns' )
    return p.parse()


def cmp_ds_name(a, b):
    aL = a[ 'summary.name' ].split( '-' )
    bL = b[ 'summary.name' ].split( '-' )
    i = 0
    m = re.compile( '^([0-9]+)[MGT]B$' )
    while i < len( aL ) and i < len( bL ):
        ae = aL[i]
        be = bL[i]
        am = m.match( ae )
        bm = m.match( be )
        if am and bm:
            i += 1
            continue

        res = (ae > be) - (be > ae)
        if res != 0:
            return res

        i += 1
    res = (len( aL ) > len( bL )) - (len( bL ) > len( aL ))
    return res

def main():
    args = get_args()
    vsi  = vsl.vmomiConnect( args )

    container = vsi.search_by_name( args.pattern, objtype=[vim.Datastore]
                                   ) if args.pattern else None
    ds = vsi.get_obj_props( [vim.Datastore], props, root=container )
    if not ds:
        return

    maxlen = max( map( lambda x: len( x['summary.name'] ), ds ) )
    if args.header:
        hfmt = ' '.join(('{0:%s}' % maxlen,
                        '{1:>9}',
                        '{2:>19}',
                        '{3:>20}'))
        s = hfmt.format( 'NAME', 'SIZE', 'FREE', 'UNCOMMITTED' )
        print( s )

    fmt = ' '.join(( '{0:%s}' % maxlen,
                     '{1[0]:>5} {1[1]:>3}',
                     '    {2[0]:>5} {2[1]:>3} ({3:2d}%)',
                     '    {4[0]:>5} {4[1]:>3} ({5:3d}%)' ))

    for elt in sorted( ds, cmp=cmp_ds_name ):
        name = elt['summary.name']
        size = int( elt['summary.capacity'] )
        free = int( elt['summary.freeSpace'] )
        try: # Not sure why this can sometimes be unavailable
            ucom = int( elt['summary.uncommitted'] )
        except KeyError:
            ucom = 0

        s = fmt.format( name,
                        vsl.scale_size( size ).split( ' ' ),

                        vsl.scale_size( free ).split( ' ' ),
                        100 * free / size,

                        vsl.scale_size( ucom ).split( ' '),
                        100 * ucom / size )
        print( s )


##########

if __name__ == '__main__':
    main()

# vsphere-datastores ends here
