from kamaki.cli.errors import raiseCLIError, CLISyntaxError
from kamaki.cli.utils import (
format_size,
+ to_bytes,
print_dict,
pretty_keys,
page_hold,
'- 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>'
])
@command(pithos_cmds)
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()
raiseCLIError(err)
except Exception as err:
raiseCLIError(err)
+ if not self['in_bytes']:
+ for k in reply:
+ reply[k] = format_size(reply[k])
print_dict(pretty_keys(reply, '-'))
@command(pithos_cmds)
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
+ try:
+ 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:]
+ try:
+ return to_bytes(quota, format)
+ except Exception as qe:
+ raiseCLIError(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)
try:
if container is None:
self.client.set_account_quota(quota)
def format_size(size):
- units = ('B', 'K', 'M', 'G', 'T')
+ units = ('B', 'KiB', 'MiB', 'GiB', 'TiB')
try:
size = float(size)
except ValueError as err:
for unit in units:
if size < 1024:
break
- 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):
+ break
+ return int(size)
+
+
def dict2file(d, f, depth=0):
for k, v in d.items():
f.write('%s%s: ' % ('\t' * depth, k))
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)))
stdout.flush()
- user_response = stdin.read(1)
- return user_response[0] in true_responses
+ user_response = stdin.readline()
+ return user_response[0] in true_resp + ['\n']