getmountfrompath and human to bytes converter filter name survey

760 views
Skip to first unread message

Yannig Perre

unread,
Apr 2, 2016, 5:17:50 AM4/2/16
to Ansible Development
Hi all,

Recently, I was talking with amenonsen about a PR with the aim to provide a way to convert a string into bytes. You can check it out at the following location: https://github.com/ansible/ansible/pull/12074

Here is a simple example:

- name: Verify human_bytes
  tags: "human_bytes"
  assert:
    that:
        - "{{'0'|human_bytes}}        == 0"
        - "{{'0.1'|human_bytes}}      == 0"
        - "{{'0.9'|human_bytes}}      == 1"
        - "{{'1'|human_bytes}}        == 1"
        - "{{'10.00 KB'|human_bytes}} == 10240"
        - "{{   '11 MB'|human_bytes}} == 11534336"
        - "{{  '1.1 GB'|human_bytes}} == 1181116006"
The filter is not quite usefull but combined with another PR of mine (https://github.com/ansible/ansible/pull/12066), it can help people to retrieve available space of a given path. Here's an example showing a way to use it in order to check available space on /tmp before trying to do anything else:

- name: "Check /tmp space"
  hosts: localhost
  tasks:
    - debug: msg={{'/tmp'|getmountfrompath(ansible_mounts)}}
    - name: "Check there's enough space"
      fail: msg="Not enough space available"
      when: ('/tmp'|getmountfrompath(ansible_mounts)).size_available < '1M' | human_bytes

Actually, amenonsen found that human_bytes is not a very good name and that we may found better alternative. So here we are people, what do you think about? Any advice?

Dossy Shiobara

unread,
Apr 2, 2016, 12:13:18 PM4/2/16
to Ansible Development
What it's really doing is converting bytes (including in abbreviated formats, like "1 GB") to the full integer representation of number of bytes.  So, yeah, I'd call it something like bytes_to_int.



On 4/2/16 5:17 AM, Yannig Perre wrote:
Actually, amenonsen found that human_bytes is not a very good name and that we may found better alternative. So here we are people, what do you think about? Any advice?

-- 
Dossy Shiobara         |      "He realized the fastest way to change
do...@panoptic.com     |   is to laugh at your own folly -- then you
http://panoptic.com/   |   can let go and quickly move on." (p. 70) 
  * WordPress * jQuery * MySQL * Security * Business Continuity *

Mike Biancaniello

unread,
Apr 4, 2016, 11:17:36 AM4/4/16
to Ansible Development
Here is something I wrote to do something similar as well as the other way around.  I called mine 'human' to be consistent with options like 'ls -hal' and 'df -h' where the '-h' is for 'human readable'.

def fmtsize(val,targ,case='lower',base=10):
   
'''
    fmtsize will take a string representing a size and convert it to or from
    human-readable format.

    Args:
        val (str): The value to convert. Usually, this passed via pipe.
        targ (str): The target style for conversion.
           
            Options: [ '
human', 'raw' ] ## 'float' (not yet implemented)

        case (Optional[str]): The case of the human style result to be returned. Defaults to '
lower'.
           
            Options: [ '
upper', 'lower' ]

        base (Optional[int]): Specify the numerical base used in calculations. Defaults to 10.

            e.g. if base == 10, 1k = 1000;
                 if base == 2,  1k = 1024

    Returns:
      str: (if targ=='
human')
           e.g. 100g, 10m, 1k, etc

    Returns:
      int: (if targ=='
raw')
           e.g. 100000000000, 10000000, 1000, etc

    Example:
      Playbook Example::

          ---
           vars:
            interfaces:
              - name: ge-0/0/0
                speed: 1g
              - name: xe-1/0/0
                speed: 10g
         
          tasks:
          - name: show me interfaces
            debug: msg="{{ item.name }} is a {{ item.speed|fmtsize('
human',case='upper') }} interface which is {{ item.speed|fmtsize('raw')/1000000 }} Mbps"
            with_items:
              interfaces
    '''

   
# I would prefer to use the correct capitalization, but
   
# dict lookups become much harder when the input might
   
# be wrong.
   
#valid_suffixes = {'k':1,'M':2,'G':3,'T':4,'P':5}
   
#valid_suffixes = { 'K':1,'M':2,'G':3,'T':4,'P':5,'E':6,'Z':7,'Y':8 }
    valid_suffixes
= [ '', 'K','M','G','T','P','E','Z','Y' ]
   
## The power multiplier tells us how to get the number
   
## e.g. for K (1), base2 = pow(2,1*10) = 1024;    base10 = pow(10,1*3) = 1000
   
##      for M (2), base2 = pow(2,2*10) = 1048576; base10 = pow(10,2*3) = 1000000
   
## etc
   
base = int(base)
    pow_mult
= { 2: 10, 10: 3 }
    kfactor
= pow(base,pow_mult[base])
   
def _to_human(num):
       
if _is_valid_human(num):
           
## Cast to string
            num
= str(num)
           
## Force requested case.
           
if case == 'lower': return num.lower()
           
return num.upper()
       
if type(num) is str:
           
if not num.isdigit():
               
return None
            num
= int(num)
       
if type(num) not in [ int, long ]:
           
return None
       
for x in valid_suffixes:
           
if num < kfactor:
               
if case == 'lower':
                    x
= x.lower()
               
return "%s%s" % (num, x)
            num
/= kfactor
       
return None
   
def _to_raw(text):
       
if type(text) is int:
           
return text
       
if text.isdigit():
           
return int(text)
       
if not _is_valid_human(text):
           
return None
        n
= int(text[:-1])
        s
= text[-1:].upper()
        power
= valid_suffixes.index(s)*pow_mult[base]
        raw
= n*pow(base,power)
       
return raw
   
def _is_valid_human(text):
       
if str(text).isdigit():
            text
= int(text)
       
if type(text) in [ int, long ]:
            n
= text
            s
= None
       
else:
            n
= text[:-1]
           
if not n.isdigit(): return False
            n
= int(n)
            s
= text[-1:].lower()
       
if s not in [x.lower() for x in valid_suffixes]:
           
## I think I put this here in case I wanted to pass
           
##  something like '100r' that it would return what I sent it
           
## However, I'm not sure if this is a valid use-case.
           
#if n < kfactor:
           
#    return True
           
return False
       
return True
   
if targ =='human': return _to_human(val)
   
if targ =='raw': return _to_raw(val)



Reply all
Reply to author
Forward
0 new messages