Skip to content

Commit

Permalink
Fix the bindings and client libraries to work with the new polling API.
Browse files Browse the repository at this point in the history
  • Loading branch information
Randy Barlow committed Feb 10, 2014
1 parent f44fa4b commit 4e4b626
Show file tree
Hide file tree
Showing 12 changed files with 67 additions and 208 deletions.
1 change: 1 addition & 0 deletions bindings/pulp/bindings/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ def __init__(self, response_body):
self.state = response_body.get('state')
self.progress_report = response_body.get('progress_report')
self.result = response_body.get('result')
self.exception = response_body.get('exception')
self.traceback = response_body.get('traceback')
self.error = response_body.get('error')
self.spawned_tasks = []
Expand Down
10 changes: 2 additions & 8 deletions client_admin/pulp/client/admin/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ def details(self, **kwargs):
Displays detailed information about a single task. The task ID must
be in kwargs under "task-id".
"""

self.context.prompt.render_title('Task Details')

task_id = kwargs['task-id']
Expand All @@ -123,7 +122,7 @@ def details(self, **kwargs):
'start_time' : start_time,
'finish_time' : finish_time,
'result' : result,
'progress' : task.progress,
'progress' : task.progress_report,
}

if task.exception:
Expand Down Expand Up @@ -159,8 +158,6 @@ def cancel(self, **kwargs):
else:
raise e, None, sys.exc_info()[2]

# -- rendering utilities --------------------------------------------------

@staticmethod
def parse_state(task):
"""
Expand All @@ -179,10 +176,7 @@ def parse_state(task):
start_time = task.start_time or _('Unstarted')
finish_time = task.finish_time or _('Incomplete')

if task.is_rejected():
state = _('Rejected')
result = _('N/A')
elif task.is_postponed() or task.is_waiting():
if task.is_waiting():
state = _('Waiting')
result = _('Incomplete')
elif task.is_running():
Expand Down
25 changes: 4 additions & 21 deletions client_lib/pulp/client/commands/repo/status/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,32 +63,15 @@ def display_group_status(context, renderer, task_group_id):

_display_status(context, renderer, task_list)

# -- private ------------------------------------------------------------------

def _display_status(context, renderer, task_list):
"""
:type renderer: pulp.client.commands.repo.sync_publish.StatusRenderer
"""

m = _('This command may be exited by pressing ctrl+c without affecting the actual operation on the server.')
m = _('This command may be exited by pressing ctrl+c without affecting the actual operation on the '
'server.')
context.prompt.render_paragraph(m, tag='ctrl-c')

# Handle the cases where we don't want to honor the foreground request
if task_list[0].is_rejected():
announce = _('The request to synchronize repository was rejected')
description = _('This is likely due to an impending delete request for the repository.')

context.prompt.render_failure_message(announce, tag='rejected-msg')
context.prompt.render_paragraph(description, tag='rejected-desc')
return

if task_list[0].is_postponed():
a = _('The request to synchronize the repository was accepted but postponed '
'due to one or more previous requests against the repository. The sync will '
'take place at the earliest possible time.')
context.prompt.render_paragraph(a, tag='postponed')
return

try:
for task_num, task in enumerate(task_list):
quiet_waiting = task_num > 0
Expand Down Expand Up @@ -121,7 +104,7 @@ def _display_task_status(context, renderer, task_id, quiet_waiting=False):
if response.response_body.is_waiting() and not quiet_waiting:
begin_spinner.next(_('Waiting to begin next step'))
else:
renderer.display_report(response.response_body.progress)
renderer.display_report(response.response_body.progress_report)

time.sleep(poll_frequency_in_seconds)

Expand All @@ -132,7 +115,7 @@ def _display_task_status(context, renderer, task_id, quiet_waiting=False):
# package download and when the task itself reports as finished. We
# don't want to leave the UI in that half-finished state so this final
# call is to clean up and render the completed report.
renderer.display_report(response.response_body.progress)
renderer.display_report(response.response_body.progress_report)

if response.response_body.was_failure():
sys.exit(1)
Expand Down
16 changes: 0 additions & 16 deletions client_lib/pulp/client/commands/repo/status/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,6 @@ def relevant_existing_task_id(existing_sync_tasks):
return None


def relevant_existing_task_group_id(existing_tasks):
"""
Grok through a list of existing tasks and look for the task_group_id
for the highest priority.
"""
running_tasks = [t for t in existing_tasks if t.is_running()]
waiting_tasks = [t for t in existing_tasks if t.is_waiting()]

if running_tasks:
return running_tasks[0].task_group_id
elif waiting_tasks:
return waiting_tasks[0].task_group_id

return None


def publish_task_in_sync_task_group(task_list):
"""
Grok through the tasks returned from the server's repo sync call and find
Expand Down
31 changes: 14 additions & 17 deletions client_lib/pulp/client/commands/repo/sync_publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from gettext import gettext as _

from pulp.client.commands import options, polling
from pulp.client.commands.repo.status import tasks
from pulp.client.commands.repo.status import status, tasks
from pulp.client.extensions.extensions import PulpCliCommand, PulpCliOptionGroup


Expand Down Expand Up @@ -76,13 +76,13 @@ def run(self, **kwargs):
# See if an existing sync is running for the repo. If it is, resume
# progress tracking.
existing_sync_tasks = self.context.server.tasks.get_repo_sync_tasks(repo_id).response_body
task_group_id = tasks.relevant_existing_task_group_id(existing_sync_tasks)

if task_group_id is not None:
if existing_sync_tasks:
msg = _('A sync task is already in progress for this repository. ')
if not background:
msg += _('Its progress will be tracked below.')
self.context.prompt.render_paragraph(msg, tag='in-progress')
self.poll([existing_sync_tasks[0]], kwargs)

else:
# Trigger the actual sync
Expand All @@ -95,7 +95,8 @@ def progress(self, task, spinner):
self.renderer.display_report(task.progress_report)

def task_header(self, task):
print task.tags
# We don't want any task header printed for this task
pass


class SyncStatusCommand(polling.PollingCommand):
Expand All @@ -118,13 +119,12 @@ def run(self, **kwargs):

# Load the relevant task group
existing_sync_tasks = self.context.server.tasks.get_repo_sync_tasks(repo_id).response_body
task_group_id = tasks.relevant_existing_task_group_id(existing_sync_tasks)

if task_group_id is None:
if not existing_sync_tasks:
msg = _('The repository is not performing any operations')
self.prompt.render_paragraph(msg, tag='no-tasks')
else:
status.display_group_status(self.context, self.renderer, task_group_id)
self.poll(existing_sync_tasks, kwargs)


class RunPublishRepositoryCommand(polling.PollingCommand):
Expand Down Expand Up @@ -217,18 +217,16 @@ def run(self, **kwargs):
msg = _('The status of this publish can be displayed using the status command.')
self.context.prompt.render_paragraph(msg, 'background')


def generate_override_config(self, **kwargs):
"""
Check if any of the override config options is passed by the user and create override_config
dictionary
:param kwargs: all keyword arguments passed in by the user on the command line
:type kwargs: dict
:return: config option dictionary consisting of option values passed by user for valid publish config options
(stored in override_config_keywords)
:rtype: dict
:type kwargs: dict
:return: config option dictionary consisting of option values passed by user for valid publish
config options (stored in override_config_keywords)
:rtype: dict
"""
override_config = {}
for option in self.override_config_keywords:
Expand Down Expand Up @@ -257,11 +255,10 @@ def run(self, **kwargs):
self.prompt.render_title(_('Repository Status [%(r)s]') % {'r' : repo_id})

# Load the relevant task group
existing_sync_tasks = self.context.server.tasks.get_repo_publish_tasks(repo_id).response_body
task_group_id = tasks.relevant_existing_task_group_id(existing_sync_tasks)
existing_publish_tasks = self.context.server.tasks.get_repo_publish_tasks(repo_id).response_body

if task_group_id is None:
if not existing_publish_tasks:
msg = _('The repository is not performing any operations')
self.prompt.render_paragraph(msg, tag='no-tasks')
else:
status.display_group_status(self.context, self.renderer, task_group_id)
status.display_group_status(self.context, self.renderer, existing_publish_tasks)
51 changes: 0 additions & 51 deletions client_lib/test/unit/client/commands/test_polling.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,28 +276,6 @@ def test_poll_empty_list(self):
self.assertTrue(isinstance(completed_tasks, list))
self.assertEqual(0, len(completed_tasks))

def test_poll_rejected(self):
"""
Task Count: 2
Statuses: Rejected (according to server behavior, all will be rejected if one is)
"""

# Setup
sim = TaskSimulator()
sim.install(self.bindings)

sim.add_task_state('1', STATE_ERROR, response=RESPONSE_REJECTED)
sim.add_task_state('2', STATE_ERROR, response=RESPONSE_REJECTED)

# Test
task_list = sim.get_all_tasks().response_body
completed_tasks = self.command.poll(task_list, {})

# Verify
self.assertEqual(completed_tasks, RESULT_REJECTED)

self.assertEqual(self.prompt.get_write_tags(), ['rejected'])

def test_failed_task(self):
"""
Task Count: 3
Expand Down Expand Up @@ -357,35 +335,6 @@ def test_cancelled_task(self):
'running-spinner','cancelled']
self.assertEqual(expected_tags, self.prompt.get_write_tags())

def test_postponed_task(self):
"""
Task Count: 1
Statuses: Postponed (test will eventually run it)
Results: 1 Success
"""

# Setup
sim = TaskSimulator()
sim.install(self.bindings)

# Remain postponed for two polls and then runs successfully
sim.add_task_state('1', STATE_WAITING, response=RESPONSE_POSTPONED)
sim.add_task_state('1', STATE_WAITING, response=RESPONSE_POSTPONED)
states = [STATE_RUNNING, STATE_FINISHED]
sim.add_task_states('1', states)

# Test
task_list = sim.get_all_tasks().response_body
completed_tasks = self.command.poll(task_list, {})

# Verify
self.assertTrue(isinstance(completed_tasks, list))
self.assertEqual(1, len(completed_tasks))

expected_tags = ['abort', 'delayed-spinner', 'delayed-spinner', 'running-spinner',
'running-spinner', 'succeeded']
self.assertEqual(expected_tags, self.prompt.get_write_tags())

def test_keyboard_interrupt(self):
# Setup
mock_poll_call = mock.MagicMock()._poll_task
Expand Down
25 changes: 0 additions & 25 deletions client_lib/test/unit/test_client_sync_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,31 +96,6 @@ def interrupt(context, renderer, task_id, quiet_waiting=True):
expected_quiet = i > 0
self.assertEqual(call_args[1]['quiet_waiting'], expected_quiet)

def test_display_status_rejected(self):
# Setup
rejected_task = Task(TASK_TEMPLATE)
rejected_task.response = RESPONSE_REJECTED

# Test
status._display_status(self.context, self.renderer, [rejected_task])

# Verify
expected_tags = ['ctrl-c', 'rejected-msg', 'rejected-desc']
self.assertEqual(expected_tags, self.prompt.get_write_tags())

def test_display_status_postponed(self):
# Setup
postponed_task = Task(TASK_TEMPLATE)
postponed_task.response = RESPONSE_POSTPONED
postponed_task.state = STATE_WAITING

# Test
status._display_status(self.context, self.renderer, [postponed_task])

# Verify
expected_tags = ['ctrl-c', 'postponed']
self.assertEqual(expected_tags, self.prompt.get_write_tags())

@mock.patch('pulp.bindings.tasks.TasksAPI.get_task')
@mock.patch('pulp.client.extensions.core.PulpPrompt.create_spinner')
def test_internal_display_task_status(self, mock_create, mock_get):
Expand Down
Loading

0 comments on commit 4e4b626

Please sign in to comment.