← Engineering articles

Practical guide and proposed lab · Controller and fabric

Catalyst Center API Task Polling: Does a Task ID Mean Success?

Build bounded Catalyst Center task polling with synthetic responses, schema checks and unresolved deadlines before validating controller readback.

An API request moving through a task queue — conceptual illustration

What you’ll learn

  • An accepted request is not a successful device change.
  • Bound polling and preserve the task identifier.
  • Verify the affected resource after task completion.

A script receives a task identifier from Catalyst Center and immediately displays success. The controller may still be processing the request, or the task may later fail. Reliable automation needs to track both the request and the resulting work.

Lab status: This is a proposed exercise, not a completed device test or client case study. Code examples require validation against your image and dependency versions. Controller/fabric platform access is not confirmed; offline samples demonstrate report logic only. My documented background is NOC/data center operations, multi-vendor Netmiko workflows and Python/Flask integration.

Offline example checks: October 20, 2026: the added helper/demo block executed with local fixtures, and related negative cases were checked offline. No live device, controller, fabric or service behavior was validated.

How does an asynchronous task differ from the API request?

Some Catalyst Center APIs accept work and return a task reference. The HTTP response describes request acceptance; the task resource describes subsequent execution. Exact response codes, fields and endpoints depend on the API and controller version. Inspect the documented response rather than assuming every endpoint uses the same structure.

Task IDs identify accepted asynchronous work. isError: false while endTime is absent is not a terminal success. Schema types and task resource paths vary by release; this example follows the documented task-style response and rejects an unfamiliar schema.

Why should a dashboard distinguish accepted from completed?

Use explicit states: accepted, pending, failed, completed-pending-readback and unresolved. A local polling deadline stops observation, not necessarily the remote task. Persist the task ID and request correlation data so an operator can reconcile without submitting a second write.

Track acceptance through completion
Conceptual diagnostic sequence; no measured outcomes or real device screenshots are shown. Open full-size diagram.

Proposed controller lab and offline task-state exercise

Start with synthetic sequences: pending-to-completed, pending-to-failed, malformed JSON shape and deadline exhaustion. GNS3/EVE-NG supplies routers, not automatically Catalyst Center licensing or a supported appliance. The supplied polling test makes no controller requests.

def task_state(payload):
    task = payload.get("response")
    if not isinstance(task, dict):
        return "unknown"
    if task.get("isError") is True:
        return "failed"
    if task.get("isError") is False and task.get("endTime"):
        return "completed"
    return "pending"

sample = {"response": {"isError": False}}
print(task_state(sample))  # Synthetic input: pending

What should a bounded task-polling loop handle?

The complete loop below accepts a fetch(task_id, timeout_seconds) adapter and never submits a write. A live adapter must issue a TLS-verified, authenticated GET to the installed release’s task endpoint, reject redirects, call raise_for_status() and validate JSON. It must not follow arbitrary URLs from an untrusted response. Exceptions remain execution failures at the worker boundary; they are not converted into task completion.

Worked Python example and input contract

import re
import time

def poll_task(fetch, task_id, deadline_seconds=30, interval=2,
              clock=time.monotonic, sleep=time.sleep):
    if deadline_seconds <= 0 or interval <= 0:
        raise ValueError('positive_polling_budget_and_interval_required')
    if not re.fullmatch(r'[A-Za-z0-9-]{1,128}', task_id):
        raise ValueError('invalid_task_id')
    deadline = clock()+deadline_seconds
    while clock() < deadline:
        remaining = deadline-clock()
        if remaining <= 0:
            break
        payload = fetch(task_id, min(5, remaining))
        task = payload.get('response') if isinstance(payload, dict) else None
        if not isinstance(task, dict) or not isinstance(task.get('isError'), bool):
            return {'state': 'unknown_schema', 'task_id': task_id}
        if task['isError']:
            return {'state': 'failed', 'task_id': task_id}
        end = task.get('endTime')
        if end is not None and (isinstance(end, bool) or not isinstance(end, (int,float))):
            return {'state': 'unknown_schema', 'task_id': task_id}
        if end and end > 0:
            return {'state': 'completed_requires_readback', 'task_id': task_id}
        sleep(max(0, min(interval, deadline-clock())))
    return {'state': 'unresolved_deadline', 'task_id': task_id}

samples = iter([{'response': {'isError': False}},
                {'response': {'isError': False, 'endTime': 1}}])
def offline_fetch(task_id, timeout):
    return next(samples)
print(poll_task(offline_fetch, 'synthetic-task', sleep=lambda seconds: None))

What device state should be checked after task completion?

Read the affected resource independently and compare required fields after completion. A controller task may complete while the service still lacks connectivity. Record the readback’s own timestamp and errors instead of inheriting the task’s status.

What should a task-tracking integration deliver?

A scoped tool can persist task identity, bounded observation history, readback evidence and ownership of unresolved work. Do not expose arbitrary controller writes through a dashboard. A mock-tested polling loop establishes local state handling only, not support for a particular controller deployment.

Explore the network automation troubleshooting collection to connect this issue to adjacent workflows. The Netmiko, NETCONF and RESTCONF comparison helps when you are choosing an interface rather than fixing an existing implementation.

Technical references

Discuss a related technical problem

Need reliable controller job status in a dashboard?

I can assess a Python/Flask integration that tracks task identifiers, timeouts and evidence. A supported controller lab and version-specific API review are prerequisites for live validation.

Discuss your project Review Imran Sarwar’s experience

Remote English-language inquiries: USA, UK, Canada, Europe and beyond. UAE-based (UTC+4); working overlap is agreed per project.