HomeGuidesAPI ReferenceGuidesMRT APIConfiguration API
GitHubAirheads Developer Community
Guides

MSP Control Tower

Reference implementation showcasing MSP tenant discovery, token exchange, and cross-tenant monitoring with PyCentral

📘

Source Code

You can find the full source code and documentation for this workflow on GitHub: MSP Control Tower

Monitor every tenant you manage with a single MSP credential. The tool discovers your managed tenants, then collects sites, devices, clients, and alerts from each one. No per-tenant credentials
are needed. Pycentral's MSP module exchanges your MSP token for a tenant-scoped token automatically (token exchange).

It ships in two forms: a web dashboard for interactive exploration and a Python CLI (main.py) for scripted export.

🚧

Note

This is a proof of concept for getting started with the MSP APIs in Central. It is not optimized for large-scale production use. Use it as a reference for your own MSP integrations.

Features

  • One MSP credential, all tenants: discovers every managed tenant and pulls sites, devices, clients, and alerts from each. No per-tenant credentials needed.
  • Animated token-exchange view that walks through each step of the flow, shown for every tenant interaction.
  • Demo mode: explore three sample tenants with a simulated token exchange, no credentials required.
  • Dashboard backend that refreshes the overview every 15 minutes and fetches per-tenant detail on demand.
  • Configurable drilldown: pick which data types (devices, clients, alerts) to fetch per tenant.
  • Interactive CLI (main.py): drill into any tenant from the terminal — browse the numbered overview, open a tenant's Sites/Devices/Clients/Alerts tabs, search and expand rows, then jump back to the list or into another tenant. Same drill-in experience as the dashboard, in your shell.
  • Scriptable export: the CLI also runs one-shot to export the cross-tenant overview to JSON and CSV.
  • Dark / light / system theme, persisted across sessions.

The flow has two stages: discover tenants at the MSP level, then exchange into each tenant. It maps directly onto the pycentral MSPBase API:

API Calls

Overview

Two calls at the MSP level discover tenants and resolve their workspace IDs before any per-tenant work begins.

StepServiceMethodEndpointDescription
1CentralGETnetwork-msp/v1/list-tenantsDiscovers all tenants managed by the MSP
2GLPGETworkspaces/v1/msp-tenantsResolves tenant name → GLP workspace ID

Per-tenant (token exchange + detail)

These calls run on demand — triggered when a user clicks into a tenant card in the dashboard, or when the CLI fetches detail. pycentral exchanges the MSP token for a tenant-scoped connection (step 1), then fetches detail in parallel (steps 2–5).

StepServiceMethodEndpointDescription
1GLPPOST{base_url}/{workspace_id}/tokenToken exchange (MSP token → tenant-scoped token)
2CentralGETnetwork-monitoring/v1/sites-healthTenant sites
3CentralGETnetwork-monitoring/v1/device-inventoryTenant device inventory
4CentralGETnetwork-monitoring/v1/clientsTenant connected clients
5CentralGETnetwork-notifications/v1/alertsTenant alerts

Prerequisites

  • Python ≥ 3.10

Installation

  1. Clone the repository and navigate to the project folder
git clone -b "v2(pre-release)" https://github.com/aruba/central-python-workflows.git
cd msp-tenant-monitoring
  1. Create and activate a virtual environment
python3 -m venv .venv
source .venv/bin/activate  # On Windows use: .venv\Scripts\activate
  1. Install dependencies
pip install -r requirements.txt

This workflow is tested against pycentral 2.0a19. Please check compatibility before executing on newer versions as there may be changes in the MSP API surface.

Configuration

Credentials Configuration

Copy the example file and fill in your MSP credentials:

cp token.yaml.example token.yaml

token.yaml uses the pycentral v2 unified format:

unified:
  client_id: <your-glp-client-id>
  client_secret: <your-glp-client-secret>
  workspace_id: <your-msp-workspace-id>     # MSP GLP Workspace ID, not a tenant ID
  base_url: https://internal.api.central.arubanetworks.com

📘

Note

For details on each credential attribute (client_id, client_secret, workspace_id, base_url) and how to obtain them, see the One-Time Setup section of the Token Exchange Guide

Region / Base URL

Set base_url in token.yaml to the API gateway for your Central account. This is determined based on the location of your HPE Aruba Networking Central account. You can use this guide to identify how to find the base URL of your account

Demo Mode (No Credentials)

Demo mode lets you explore the full dashboard, including the animated token-exchange modal, without any MSP credentials.

  1. Start the server: python3 server.py
  2. Open http://localhost:8000/
  3. Click "Try demo mode" on the login screen
  4. Explore 3 pre-loaded tenants with simulated token exchange

📘

Note

Demo mode replays pre-built sample data. The exchange modal is fully animated and shows a "Simulated" badge, so you can learn the token-exchange flow without a live MSP connection. All tabs (Sites, Devices, Clients, Alerts) are populated from the sample data.

Execution

  1. Start the dashboard (UI + API on port 8000):
python3 server.py
# open http://localhost:8000/

Log in with your MSP credentials or click "Try demo mode" to explore without credentials. The overview refreshes in the background every 15 minutes; per-tenant detail is fetched on demand when you open a tenant's tabs.

  1. Explore tenants interactively in the terminal:
python3 main.py

This starts an interactive session. You get a numbered cross-tenant overview; type a tenant number to drill in, then use the on-screen menus to navigate:

  • Overview → type a tenant number to open it, or q to quit.
  • Tenant menu[s]ites, [d]evices, [c]lients, [a]lerts; [b]ack returns to the tenant list (open another tenant); [q]uit.
  • Inside a tab/text to search, a row number to expand that row's full detail, r to refresh, b back to the tenant menu, q to quit.

Per-tenant detail is fetched on demand the first time you open each tab and cached for the session (r forces a re-fetch). Add --tenant NAME_OR_ID to start the session pre-filtered to one tenant.

Command Line Options

FlagTypeDescriptionRequired
--tenant NAME_OR_IDstringFilter to a single tenant (name substring or ID); applies to both interactive and export modesNo
--export-json [PATH]flagOne-shot: export the overview to JSON (default output/sample_output.json) and exitNo
--export-csv [PATH]flagOne-shot: export the overview to CSV (default output/sample_output.csv) and exitNo
--verboseflagEnable DEBUG logging (otherwise the interactive CLI stays quiet)No

Output

On-Screen Output

The dashboard surfaces a full cross-tenant view:

  • Overview KPIs: total device, client, site, and alert counts across all managed tenants
  • Tenant cards with health bars and per-tenant alert counts. Click any card to drill into tenant detail.
  • Per-tenant drill-down with four tabs: Sites, Devices, Clients, and Alerts. Each tab loads independently on demand.
  • Token exchange modal that animates four steps (MSP credential → GLP token request → MSP token → tenant token exchange) with live status indicators. Shows a "Simulated" badge in demo mode.

The interactive CLI mirrors the drill-in experience in the terminal:

  • A fleet-totals panel followed by a numbered tenant table (sites, devices, critical-alert counts per tenant)
  • Drill into any tenant and page through the same four tabs — Sites, Devices, Clients, Alerts — each fetched on demand and cached for the session
  • Row expansion shows the full record (e.g. a device's serial, MAC, role, and firmware), /text search filters the current table, and you can refresh (r) or jump back to open another tenant

Report Files

From the CLI (--export-json / --export-csv):

  • output/msp_export.json: full JSON export of all tenant summaries, sites, devices, clients, and alerts
  • output/msp_export.csv: CSV summary suitable for spreadsheet review

See output/sample_output.json for an example of the JSON schema.

Troubleshooting

ProblemFix
"Could not reach the API gateway"Check the base_url / region. Use the region table in the Configuration section to find your gateway.
"Token request rejected"Verify the Client ID and Client Secret in token.yaml or the login form match the API client in your GLP portal.
"No tenants returned"workspace_id is probably a tenant workspace ID. Use the MSP GLP workspace ID (found in the GLP portal under your MSP organization).
Python version error on startupPython ≥ 3.10 required. Check your version with python3 --version and recreate the venv with a newer interpreter.
Dashboard shows no dataCheck GET /api/status for last_refresh_ts; force a refresh via POST /api/refresh and watch server.py logs for errors.

Support