Commit 001200c3 authored by Stavros Sachtouris's avatar Stavros Sachtouris
Browse files

Format data size units, use it in quota commands

quota returns value in units (KiB, MiB, etc)
new argument -b, --bytes to return value in bytes
setquota can accept a unit string
    setquota 2.3GB
parent 7147e1ca
......@@ -36,6 +36,7 @@ from kamaki.cli.command_tree import CommandTree
from kamaki.cli.errors import raiseCLIError, CLISyntaxError
from kamaki.cli.utils import (
......@@ -88,7 +89,7 @@ def raise_connection_errors(e):
'- total quota: /store quota',
'- container quota: /store quota <container>',
'Users shall set a higher container quota, if available:',
'- /store setquota <limit in KB> <container>'
'- /store setquota <quota>[unit] <container>'
......@@ -1780,7 +1781,11 @@ class store_delmeta(_store_container_command):
class store_quota(_store_account_command):
"""Get quota (in KB) for account or container"""
"""Get quota for account or container"""
arguments = dict(
in_bytes=FlagArgument('Show result in bytes', ('-b', '--bytes'))
def main(self, container=None):
super(self.__class__, self).main()
......@@ -1799,15 +1804,47 @@ class store_quota(_store_account_command):
except Exception as err:
if not self['in_bytes']:
for k in reply:
reply[k] = format_size(reply[k])
print_dict(pretty_keys(reply, '-'))
class store_setquota(_store_account_command):
"""Set new quota (in KB) for account or container"""
"""Set new quota for account or container
By default, quota is set in bytes
Users may specify a different unit, e.g:
/store setquota 2.3GB mycontainer
Accepted units: B, KiB (1024 B), KB (1000 B), MiB, MB, GiB, GB, TiB, TB
def _calculate_quota(self, user_input):
quota = 0
quota = int(user_input)
except ValueError:
index = 0
digits = [str(num) for num in range(0, 10)] + ['.']
while user_input[index] in digits:
index += 1
quota = user_input[:index]
format = user_input[index:]
return to_bytes(quota, format)
except Exception as qe:
'Failed to convert %s to bytes' % user_input,
details=['Syntax: setquota <quota>[format] [container]',
'e.g.: setquota 2.3GB mycontainer',
'Acceptable formats:',
'(*1024): B, KiB, MiB, GiB, TiB',
'(*1000): B, KB, MB, GB, TB'])
return quota
def main(self, quota, container=None):
super(self.__class__, self).main()
quota = self._calculate_quota(quota)
if container is None:
......@@ -257,7 +257,7 @@ def print_items(items,
def format_size(size):
units = ('B', 'K', 'M', 'G', 'T')
units = ('B', 'KiB', 'MiB', 'GiB', 'TiB')
size = float(size)
except ValueError as err:
......@@ -265,13 +265,37 @@ def format_size(size):
for unit in units:
if size < 1024:
size /= 1024
s = ('%.1f' % size)
if '.0' == s[-2:]:
s = s[:-2]
size /= 1024.0
s = ('%.2f' % size)
while '.' in s and s[-1] in ('0', '.'):
s = s[:-1]
return s + unit
def to_bytes(size, format):
:param size: (float) the size in the given format
:param format: (case insensitive) KiB, KB, MiB, MB, GiB, GB, TiB, TB
:returns: (int) the size in bytes
format = format.upper()
if format == 'B':
return int(size)
size = float(size)
units_dc = ('KB', 'MB', 'GB', 'TB')
units_bi = ('KIB', 'MIB', 'GIB', 'TIB')
factor = 1024 if format in units_bi else 1000 if format in units_dc else 0
if not factor:
raise ValueError('Invalid data size format %s' % format)
for prefix in ('K', 'M', 'G', 'T'):
size *= factor
if format.startswith(prefix):
return int(size)
def dict2file(d, f, depth=0):
for k, v in d.items():
f.write('%s%s: ' % ('\t' * depth, k))
......@@ -325,14 +349,14 @@ def split_input(line):
return terms
def ask_user(msg, true_responses=('Y', 'y')):
def ask_user(msg, true_resp=['Y', 'y']):
"""Print msg and read user response
:param true_responses: (tuple of chars)
:param true_resp: (tuple of chars)
:returns: (bool) True if reponse in true responses, False otherwise
stdout.write('%s (%s for yes):' % (msg, true_responses))
stdout.write('%s (%s or enter for yes):' % (msg, ', '.join(true_resp)))
user_response =
return user_response[0] in true_responses
user_response = stdin.readline()
return user_response[0] in true_resp + ['\n']
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment