Commit e9c73313 authored by Stavros Sachtouris's avatar Stavros Sachtouris
Browse files

Modify progress bar behavior in cyclades wait

Refs: #4352

Progress bar is now able to "count down", be "eating" the bar instead of
filling it, thus has meaning for timeouts
All waits are time-outs, except for "server BUILD"
parent a9598baf
......@@ -332,7 +332,7 @@ class ProgressBarArgument(FlagArgument):
newarg._value = self._value
return newarg
def get_generator(self, message, message_len=25):
def get_generator(self, message, message_len=25, timeout=False):
"""Get a generator to handle progress of the bar (gen.next())"""
if self.value:
return None
......@@ -341,8 +341,18 @@ class ProgressBarArgument(FlagArgument):
except NameError:
self.value = None
return self.value
if timeout:
bar_phases = list(self.bar.phases)
bar_phases[0], bar_phases[-1] = bar_phases[-1], ''
self.bar.phases = bar_phases
self.bar.empty_fill = bar_phases[0]
self.bar.bar_prefix = ' (Timeout:'
self.bar.bar_suffix = ' '
self.bar.suffix = '%(eta)ds)'
self.bar.eta = 120
else:
self.bar.suffix = '%(percent)d%% - %(eta)ds'
self.bar.message = message.ljust(message_len)
self.bar.suffix = '%(percent)d%% - %(eta)ds'
self.bar.start()
def progress_gen(n):
......
......@@ -369,13 +369,29 @@ class ProgressBarArgument(TestCase):
pba.value = None
msg, msg_len = 'message', 40
with patch('%s.KamakiProgressBar.start' % arg_path) as start:
pba.get_generator(msg, msg_len)
self.assertTrue(isinstance(pba.bar, argument.KamakiProgressBar))
self.assertNotEqual(pba.bar.message, msg)
self.assertEqual(
pba.bar.message, '%s%s' % (msg, ' ' * (msg_len - len(msg))))
self.assertEqual(pba.bar.suffix, '%(percent)d%% - %(eta)ds')
start.assert_called_once()
try:
pba.get_generator(msg, msg_len)
self.assertTrue(
isinstance(pba.bar, argument.KamakiProgressBar))
self.assertNotEqual(pba.bar.message, msg)
self.assertEqual(pba.bar.message, '%s%s' % (
msg, ' ' * (msg_len - len(msg))))
self.assertEqual(pba.bar.suffix, '%(percent)d%% - %(eta)ds')
start.assert_called_once()
pba.get_generator(msg, msg_len, timeout=True)
self.assertTrue(
isinstance(pba.bar, argument.KamakiProgressBar))
self.assertNotEqual(pba.bar.message, msg)
self.assertEqual(pba.bar.message, '%s%s' % (
msg, ' ' * (msg_len - len(msg))))
self.assertEqual(pba.bar.bar_prefix, ' (Timeout:')
self.assertEqual(pba.bar.suffix, '%(eta)ds)')
finally:
try:
pba.finish()
except Exception:
pass
def test_finish(self):
pba = argument.ProgressBarArgument(parsed_name='--progress')
......
......@@ -177,12 +177,12 @@ class _command_init(object):
assert max_threads > 0, 'invalid max_threads config option'
self.client.MAX_THREADS = max_threads
def _safe_progress_bar(self, msg, arg='progress_bar'):
def _safe_progress_bar(self, msg, arg='progress_bar', timeout=False):
"""Try to get a progress bar, but do not raise errors"""
try:
progress_bar = self.arguments[arg]
progress_bar.file = self._err
gen = progress_bar.get_generator(msg)
gen = progress_bar.get_generator(msg, timeout=timeout)
except Exception:
return (None, None)
return (progress_bar, gen)
......
......@@ -75,20 +75,23 @@ class _service_wait(object):
'do not show progress bar', ('-N', '--no-progress-bar'), False)
)
def _wait(self, service, service_id, status_method, currect_status):
def _wait(
self, service, service_id, status_method, current_status,
timeout=True):
(progress_bar, wait_cb) = self._safe_progress_bar(
'%s %s: periodically check if status is %s' % (
service, service_id, currect_status))
'%s %s: status is still %s' % (
service, service_id, current_status),
timeout=timeout)
try:
new_mode = status_method(
service_id, currect_status, wait_cb=wait_cb)
service_id, current_status, wait_cb=wait_cb)
if new_mode:
self.error('\n%s %s: status is %s' % (
self.error('%s %s: status is now %s' % (
service, service_id, new_mode))
else:
self.error('\nTime out: %s %s still in %s' % (
service, service_id, currect_status))
self.error('%s %s: (timeout) status is still %s' % (
service, service_id, current_status))
except KeyboardInterrupt:
self.error('\n- canceled')
finally:
......@@ -97,16 +100,17 @@ class _service_wait(object):
class _server_wait(_service_wait):
def _wait(self, server_id, currect_status):
def _wait(self, server_id, current_status):
super(_server_wait, self)._wait(
'Server', server_id, self.client.wait_server, currect_status)
'Server', server_id, self.client.wait_server, current_status,
timeout=(current_status not in ('BUILD', )))
class _network_wait(_service_wait):
def _wait(self, net_id, currect_status):
def _wait(self, net_id, current_status):
super(_network_wait, self)._wait(
'Network', net_id, self.client.wait_network, currect_status)
'Network', net_id, self.client.wait_network, current_status)
class _init_cyclades(_command_init):
......@@ -699,12 +703,19 @@ class server_wait(_init_cyclades, _server_wait):
@errors.generic.all
@errors.cyclades.connection
@errors.cyclades.server_id
def _run(self, server_id, currect_status):
self._wait(server_id, currect_status)
def _run(self, server_id, current_status):
r = self.client.get_server_details(server_id)
if r['status'].lower() == current_status.lower():
self._wait(server_id, current_status)
else:
self.error(
'Server %s: Cannot wait for status %s, '
'status is already %s' % (
server_id, current_status, r['status']))
def main(self, server_id, currect_status='BUILD'):
def main(self, server_id, current_status='BUILD'):
super(self.__class__, self)._run()
self._run(server_id=server_id, currect_status=currect_status)
self._run(server_id=server_id, current_status=current_status)
@command(flavor_cmds)
......@@ -946,7 +957,7 @@ class network_create(_init_cyclades, _optional_json, _network_wait):
type=self['type'])
_add_name(self, r)
self._print(r, self.print_dict)
if self['wait']:
if self['wait'] and r['status'] in ('PENDING', ):
self._wait(r['id'], 'PENDING')
def main(self, name):
......@@ -1055,12 +1066,19 @@ class network_wait(_init_cyclades, _network_wait):
@errors.generic.all
@errors.cyclades.connection
@errors.cyclades.network_id
def _run(self, network_id, currect_status):
self._wait(network_id, currect_status)
def _run(self, network_id, current_status):
net = self.client.get_network_details(network_id)
if net['status'].lower() == current_status.lower():
self._wait(network_id, current_status)
else:
self.error(
'Network %s: Cannot wait for status %s, '
'status is already %s' % (
network_id, current_status, net['status']))
def main(self, network_id, currect_status='PENDING'):
def main(self, network_id, current_status='PENDING'):
super(self.__class__, self)._run()
self._run(network_id=network_id, currect_status=currect_status)
self._run(network_id=network_id, current_status=current_status)
@command(server_cmds)
......
......@@ -295,14 +295,20 @@ class CycladesClient(CycladesRestClient):
:returns: (str) the new mode if successful, (bool) False if timed out
"""
status, progress = get_status(self, item_id)
if status != current_status:
return status
old_wait = total_wait = 0
if wait_cb:
wait_gen = wait_cb(1 + max_wait // delay)
wait_gen = wait_cb(max_wait // delay)
wait_gen.next()
if status != current_status:
if wait_cb:
try:
wait_gen.next()
except Exception:
pass
return status
old_wait = total_wait = 0
while status == current_status and total_wait <= max_wait:
if wait_cb:
try:
......@@ -310,11 +316,8 @@ class CycladesClient(CycladesRestClient):
wait_gen.next()
except Exception:
break
else:
stdout.write('.')
stdout.flush()
old_wait = total_wait
total_wait = progress or (total_wait + 1)
total_wait = progress or total_wait + 1
sleep(delay)
status, progress = get_status(self, item_id)
......
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