Skip to content

yuanfmjohn/bulkqkview

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 

Repository files navigation

bulkqkview

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.


Table of Contents

  1. Overview
  2. Requirements
  3. Installation
  4. Credential Requirements
  5. Usage
  6. All Command-Line Options
  7. Output
  8. Technical Notes

Overview

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.


Requirements

Python

Python 3.10 or later (uses X | Y union type hints).

Python packages

aiohttp>=3.9.0

Install with:

pip install -r requirements.txt

requirements.txt:

aiohttp>=3.9.0

Network access

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).


Installation

git clone <repo-url>
cd bulkqkview
pip install -r requirements.txt

Credential Requirements

BIG-IP Credentials

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-info
  • GET /mgmt/tm/sys/global-settings
  • POST /mgmt/cm/autodeploy/qkview
  • GET /mgmt/cm/autodeploy/qkview/{id}
  • GET /mgmt/shared/file-transfer/ucs-downloads/*

The built-in admin role satisfies all of these.


F5 iHealth OAuth2 API Credentials

Important: --ihealth-client-id and --ihealth-client-secret are 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.

How to obtain OAuth2 API credentials

Full instructions are in the F5 Knowledge Base article:

K000130498 — iHealth API: Generating OAuth2 API credentials

Summary of steps:

  1. Log in to https://ihealth2.f5.com with your F5 account.
  2. Navigate to API Credentials (or Manage API Access) in your profile settings.
  3. Click Generate New Credentials (or equivalent).
  4. Copy the Client ID and Client Secret — the secret is shown only once.
  5. Pass them to the script via --ihealth-client-id and --ihealth-client-secret, or omit them to be prompted interactively.

Technical details

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

Common error: HTTP 401 invalid_client

{
  "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.


Usage

Single Device

# 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 MyClientSecret

Multiple Devices from a File

python3 bulkqkview.py -f devices.txt -u admin -p MyPassword \
    --ihealth-client-id abcd1234 \
    --ihealth-client-secret MyClientSecret

devices.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.

Upload-Only Mode

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 C12345678

BIG-IP credentials (-u, -p) and device target (-t, -f) are not required in upload-only mode.

Interactive Credential Prompting

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 admin

Example prompt sequence:

BIG-IP password for 'admin':
iHealth OAuth2 Client ID: abcd1234
iHealth OAuth2 Client Secret:

Proxy Configuration

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:3128

All Command-Line Options

usage: 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]

Device targeting (mutually exclusive)

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

BIG-IP credentials

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

iHealth credentials

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

iHealth upload metadata

Option Default Description
--description TEXT "" Free-text description attached to the upload
--case CASE_NUM "" F5 support case number, e.g. C12345678

Proxy (iHealth traffic only)

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

Output and logging

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.)

Output

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

Exit codes

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

Technical Notes

qkview generation — async task API

The script uses the /mgmt/cm/autodeploy/qkview async task API:

  1. POST /mgmt/cm/autodeploy/qkview — creates a task and returns immediately with a task ID (no timeout risk).
  2. GET /mgmt/cm/autodeploy/qkview/{id} — polled every 30 seconds until the status is SUCCEEDED (or a failure state / 1-hour timeout).
  3. The completed task response contains a qkviewUri field with the authoritative download URL (localhost as 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.

Chunked file download

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.

iHealth authentication (Okta OAuth2)

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.

SSL verification

Connection SSL verification
BIG-IP Disabled — self-signed management certificates are standard
iHealth (token + upload) Enabled — system CA bundle

Proxy scope

The --proxy-* options affect only iHealth traffic (OAuth2 token request and qkview upload). BIG-IP connections are always made directly, regardless of proxy settings.

Concurrency model

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).

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Python 100.0%