Generate qkview diagnostic files on one or more F5 BIG-IP devices via the REST API, download them locally, and upload them to F5 iHealth for analysis — all concurrently from a single command.
- Overview
- Requirements
- Installation
- Credential Requirements
- Usage
- All Command-Line Options
- Output
- Technical Notes
bulkqkview.py automates the end-to-end qkview workflow:
BIG-IP ──► generate qkview (async REST task)
──► download qkview (chunked file-transfer API)
──► upload to F5 iHealth (OAuth2 + multipart POST)
When a file of targets is provided every device is processed concurrently, so a fleet of 20 devices takes roughly the same wall-clock time as a single device.
Python 3.10 or later (uses X | Y union type hints).
aiohttp>=3.9.0
Install with:
pip install -r requirements.txtrequirements.txt:
aiohttp>=3.9.0
| Destination | Port | Required for |
|---|---|---|
| BIG-IP management IP | 443 (HTTPS) | qkview generation & download |
identity.account.f5.com |
443 (HTTPS) | iHealth OAuth2 token |
ihealth2-api.f5.com |
443 (HTTPS) | qkview upload |
Note: BIG-IP connections go directly from the host running the script. iHealth connections can optionally be routed through an HTTP proxy (see Proxy Configuration).
git clone <repo-url>
cd bulkqkview
pip install -r requirements.txt| Argument | Description |
|---|---|
-u / --username |
BIG-IP admin username (e.g. admin) |
-p / --password |
BIG-IP admin password — prompted securely if omitted |
The account needs access to:
GET /mgmt/shared/identified-devices/config/device-infoGET /mgmt/tm/sys/global-settingsPOST /mgmt/cm/autodeploy/qkviewGET /mgmt/cm/autodeploy/qkview/{id}GET /mgmt/shared/file-transfer/ucs-downloads/*
The built-in admin role satisfies all of these.
Important:
--ihealth-client-idand--ihealth-client-secretare OAuth2 API credentials generated from the F5 iHealth portal. They are not your F5 account username and password.
F5 migrated iHealth authentication to an Okta-based OAuth2 identity platform (documented in Bug ID 1225789). The old basic-auth and legacy OAuth endpoints no longer work.
Full instructions are in the F5 Knowledge Base article:
Summary of steps:
- Log in to https://ihealth2.f5.com with your F5 account.
- Navigate to API Credentials (or Manage API Access) in your profile settings.
- Click Generate New Credentials (or equivalent).
- Copy the Client ID and Client Secret — the secret is shown only once.
- Pass them to the script via
--ihealth-client-idand--ihealth-client-secret, or omit them to be prompted interactively.
| Parameter | Value |
|---|---|
| Token URL | https://identity.account.f5.com/oauth2/ausp95ykc80HOU7SQ357/v1/token |
| Grant type | client_credentials |
| Scope | ihealth |
| Token auth | Authorization: Basic base64(client_id:client_secret) |
| Upload URL | https://ihealth2-api.f5.com/qkview-analyzer/api/qkviews |
| Upload auth | Authorization: Bearer <access_token> |
| Accept header | application/vnd.f5.ihealth.api |
{
"errorCode": "invalid_client",
"errorSummary": "Invalid value for 'client_id' parameter."
}This means the Client ID passed to the token endpoint does not exist in Okta's system. The most common cause is passing a portal username (e.g. an email address) instead of an OAuth2 Client ID. Follow K000130498 to generate the correct credentials.
# By IP address (hostname resolved automatically from the BIG-IP API)
python3 bulkqkview.py -t 192.168.1.1 -u admin -p MyPassword \
--ihealth-client-id abcd1234 \
--ihealth-client-secret MyClientSecret
# By hostname
python3 bulkqkview.py -t bigip-prod.example.com -u admin -p MyPassword \
--ihealth-client-id abcd1234 \
--ihealth-client-secret MyClientSecretpython3 bulkqkview.py -f devices.txt -u admin -p MyPassword \
--ihealth-client-id abcd1234 \
--ihealth-client-secret MyClientSecretdevices.txt format — one IP or hostname per line, blank lines and #
comments ignored:
# Production BIG-IPs
192.168.10.1
192.168.10.2
bigip-dr.example.com
# Lab
10.0.0.50
All devices are processed concurrently. Each device generates, downloads, and uploads its qkview independently.
Skip BIG-IP connection entirely. Upload every *.tar.qkview file already
present in the output directory to iHealth. Useful for:
- Retrying a failed iHealth upload without re-generating the qkview
- Uploading qkviews collected by another process or transferred from another host
# Upload *.tar.qkview files in the current directory
python3 bulkqkview.py --upload-only \
--ihealth-client-id abcd1234 \
--ihealth-client-secret MyClientSecret
# Upload from a specific directory, attach a support case
python3 bulkqkview.py --upload-only -o /var/qkviews \
--ihealth-client-id abcd1234 \
--ihealth-client-secret MyClientSecret \
--case C12345678BIG-IP credentials (-u, -p) and device target (-t, -f) are not
required in upload-only mode.
Any of -p, --ihealth-client-id, --ihealth-client-secret, and
--proxy-pass can be omitted. The script will prompt for them interactively.
Passwords and secrets are entered via getpass — input is not echoed to
the terminal.
# Prompted for BIG-IP password, iHealth client ID, and iHealth client secret
python3 bulkqkview.py -t 192.168.1.1 -u adminExample prompt sequence:
BIG-IP password for 'admin':
iHealth OAuth2 Client ID: abcd1234
iHealth OAuth2 Client Secret:
iHealth traffic (token request and qkview upload) can be routed through an HTTP proxy. BIG-IP connections always go direct — they are typically on a management network that does not use a proxy.
# Unauthenticated proxy, port specified separately
python3 bulkqkview.py -t 192.168.1.1 -u admin \
--ihealth-client-id abcd1234 --ihealth-client-secret MyClientSecret \
--proxy-host proxy.corp.com \
--proxy-port 3128
# Port embedded in --proxy-host
python3 bulkqkview.py -t 192.168.1.1 -u admin \
--ihealth-client-id abcd1234 --ihealth-client-secret MyClientSecret \
--proxy-host proxy.corp.com:3128
# Authenticated proxy (--proxy-pass prompted if omitted)
python3 bulkqkview.py -t 192.168.1.1 -u admin \
--ihealth-client-id abcd1234 --ihealth-client-secret MyClientSecret \
--proxy-host proxy.corp.com:3128 \
--proxy-user proxyuser \
--proxy-pass proxypass
# Upload-only with proxy
python3 bulkqkview.py --upload-only -o /var/qkviews \
--ihealth-client-id abcd1234 --ihealth-client-secret MyClientSecret \
--proxy-host proxy.corp.com:3128usage: bulkqkview.py [-h] (-t HOST | -f FILE | --upload-only)
[-u USERNAME] [-p PASSWORD]
[--ihealth-client-id CLIENT_ID]
[--ihealth-client-secret CLIENT_SECRET]
[--description TEXT] [--case CASE_NUM]
[--proxy-host HOST[:PORT]] [--proxy-port PORT]
[--proxy-user USER] [--proxy-pass PASS]
[-o DIR] [-v]
| Option | Description |
|---|---|
-t HOST / --target HOST |
Single BIG-IP IP address or hostname |
-f FILE / --file FILE |
Text file of BIG-IP targets, one per line |
--upload-only |
Skip generation/download; upload *.tar.qkview files from -o |
| Option | Default | Description |
|---|---|---|
-u USER / --username USER |
(required unless --upload-only) |
BIG-IP admin username |
-p PASS / --password PASS |
(prompted if omitted) | BIG-IP admin password |
| Option | Default | Description |
|---|---|---|
--ihealth-client-id ID |
(prompted if omitted) | OAuth2 Client ID — see K000130498 |
--ihealth-client-secret SECRET |
(prompted if omitted) | OAuth2 Client Secret |
| Option | Default | Description |
|---|---|---|
--description TEXT |
"" |
Free-text description attached to the upload |
--case CASE_NUM |
"" |
F5 support case number, e.g. C12345678 |
| Option | Default | Description |
|---|---|---|
--proxy-host HOST[:PORT] |
(none) | HTTP proxy hostname, optionally with port |
--proxy-port PORT |
8080 |
Proxy port when not embedded in --proxy-host |
--proxy-user USER |
(none) | Proxy authentication username |
--proxy-pass PASS |
(prompted if --proxy-user set) |
Proxy authentication password |
| Option | Default | Description |
|---|---|---|
-o DIR / --output-dir DIR |
. |
Directory for downloaded files; also scanned by --upload-only |
-v / --verbose |
off | Enable debug logging (prints raw HTTP bodies, task JSON, etc.) |
Progress is written to stdout with timestamps and log levels. Every HTTP request and response status code is logged.
Example output for a single device:
2026-03-28 21:00:00 INFO Processing 1 device(s): 192.168.1.1
2026-03-28 21:00:00 INFO qkview files will be saved to: /home/user/qkviews
2026-03-28 21:00:00 INFO [192.168.1.1] ━━ STEP 1/4 Connect & authenticate
2026-03-28 21:00:00 INFO [192.168.1.1] Connecting to BIG-IP management API: https://192.168.1.1
2026-03-28 21:00:01 INFO [192.168.1.1] Connection established (HTTP 200 OK)
2026-03-28 21:00:01 INFO [192.168.1.1] Authentication successful
2026-03-28 21:00:01 INFO [192.168.1.1] Device info: hostname=bigip-1.corp.com platform=Z100 version=17.1.0
2026-03-28 21:00:01 INFO [192.168.1.1] ━━ STEP 2/4 Generate qkview
2026-03-28 21:00:02 INFO [192.168.1.1] Creating qkview task → POST https://192.168.1.1/mgmt/cm/autodeploy/qkview
2026-03-28 21:00:02 INFO [192.168.1.1] qkview task created (id=abc-123-def)
2026-03-28 21:00:02 INFO [192.168.1.1] Polling for completion every 30s
2026-03-28 21:00:32 INFO [192.168.1.1] task status: RUNNING (poll #1, 0m 30s elapsed)
2026-03-28 21:05:32 INFO [192.168.1.1] task status: SUCCEEDED (poll #11, 5m 30s elapsed)
2026-03-28 21:05:32 INFO [192.168.1.1] ━━ STEP 3/4 Download qkview
2026-03-28 21:05:33 INFO [192.168.1.1] Initiating download → GET https://192.168.1.1/mgmt/shared/...
2026-03-28 21:05:33 INFO [192.168.1.1] Download started (HTTP 206 Partial Content)
2026-03-28 21:05:40 INFO [192.168.1.1] Downloading ... 10.0 / 47.3 MiB (21.1%)
2026-03-28 21:06:15 INFO [192.168.1.1] Download complete: 47.3 MiB written to qkview_bigip-1.corp.com_20260328_210001.tar.qkview
2026-03-28 21:06:15 INFO [192.168.1.1] ━━ STEP 4/4 Upload to F5 iHealth
2026-03-28 21:06:15 INFO [iHealth] Authenticating with iHealth OAuth2
2026-03-28 21:06:15 INFO [iHealth] Requesting OAuth2 Bearer token → POST https://identity.account.f5.com/...
2026-03-28 21:06:16 INFO [iHealth] Bearer token obtained successfully
2026-03-28 21:06:16 INFO [iHealth] Uploading qkview_bigip-1.corp.com_20260328_210001.tar.qkview (47.3 MiB)
2026-03-28 21:07:01 INFO [iHealth] API response: HTTP 303 See Other
2026-03-28 21:07:01 INFO [iHealth] Upload accepted: qkview_bigip-1.corp.com_20260328_210001.tar.qkview
2026-03-28 21:07:01 INFO [iHealth] qkview URL: https://ihealth2.f5.com/qkview-analyzer/qkviews/123456789
2026-03-28 21:07:01 INFO [192.168.1.1] ━━ All steps complete
========================================================================
SUMMARY
========================================================================
192.168.1.1 OK
Local file : ./qkview_bigip-1.corp.com_20260328_210001.tar.qkview
iHealth : https://ihealth2.f5.com/qkview-analyzer/qkviews/123456789
========================================================================
1/1 device(s) succeeded
| Code | Meaning |
|---|---|
0 |
All devices / uploads succeeded |
1 |
One or more failures, or no qkview files found in --upload-only mode |
130 |
Interrupted by Ctrl-C |
The script uses the /mgmt/cm/autodeploy/qkview async task API:
POST /mgmt/cm/autodeploy/qkview— creates a task and returns immediately with a task ID (no timeout risk).GET /mgmt/cm/autodeploy/qkview/{id}— polled every 30 seconds until the status isSUCCEEDED(or a failure state / 1-hour timeout).- The completed task response contains a
qkviewUrifield with the authoritative download URL (localhostas the host is replaced with the real device address).
This avoids the ~30-second Jetty timeout that kills synchronous qkview
generation endpoints such as /mgmt/tm/util/qkview.
BIG-IP caps each file-transfer response at approximately 1 MiB. The
script issues successive Content-Range requests until the file is complete,
clamping the final range to the known file size to avoid spurious
400/416 responses on the last chunk.
F5 migrated iHealth to an Okta-based OAuth2 identity platform (Bug ID
1225789). The old basic-auth and ihealth-api.f5.com endpoints no longer
work. References:
- K000130498 — how to generate OAuth2 API credentials for the iHealth API
- Token URL:
https://identity.account.f5.com/oauth2/ausp95ykc80HOU7SQ357/v1/token - API base:
https://ihealth2-api.f5.com
A fresh token is fetched immediately before each upload — not at startup — so authentication only occurs after the qkview has been fully downloaded.
| Connection | SSL verification |
|---|---|
| BIG-IP | Disabled — self-signed management certificates are standard |
| iHealth (token + upload) | Enabled — system CA bundle |
The --proxy-* options affect only iHealth traffic (OAuth2 token
request and qkview upload). BIG-IP connections are always made directly,
regardless of proxy settings.
Each device runs in its own asyncio task. Tasks overlap: while one device
is waiting for its qkview task to complete, another device may already be
downloading or uploading. Within a single device the four steps are strictly
sequential (connect → generate → download → upload).