Db2

Db2

Where DBAs and data experts come together to stop operating and start innovating. Connect, share, and shape the AI era with us.


#Data


#Data
 View Only

Scale Your Database Operations: A Technical Guide to Db2 Genius Hub REST APIs

By Arshnoor Kaur posted 9 days ago

  

By Nisha Choudhary, Arshnoor Kaur

1. The Challenge & Solution

Let’s start with a scenario where your enterprise needs to add 300 databases to Db2 Genius Hub for centralized monitoring. Manual addition through the web console requires 5-10 minutes per database which adds up to over 25 hours of repetitive work. This approach of manually adding each database connection introduces configuration drift, connection string errors, and diverts skilled resources from critical tasks.

Db2 Genius Hub's REST API eliminates this bottleneck. A Python script can onboard all 300 databases in minutes with consistent configuration and zero manual errors.

In this guide, we'll explore how to leverage the Db2 Genius Hub REST API to authenticate, add databases programmatically, retrieve alerts across multiple databases, and build complete automation scripts that transform database management from a manual chore into an efficient, repeatable process.

2. Introducing the Db2 Genius Hub REST API

The Db2 Genius Hub REST API provides programmatic access to database management and monitoring capabilities. Operations available in the web console are accessible programmatically, enabling integration with existing automation frameworks, CI/CD pipelines, and infrastructure-as-code workflows.

Understanding REST:

REST (Representational State Transfer) uses standard HTTP methods as actions - GET (retrieve data), POST (create new items), PUT (update existing items), and DELETE (remove items). All data exchanges use JSON format, which every programming language can easily read and write.


Key Capabilities:

  • Authentication & Security: Token-based login which requires you to authenticate once and then receiving a temporary digital key for all subsequent API calls

  • Database Connection Operations: Add, update, remove, and configure database connections programmatically

  • Monitoring Configuration: Set up event monitors, define tablespaces, and schedule blackout periods (maintenance windows)

  • Alert Management: Retrieve and analyze alerts across all monitored databases in a single API call

  • Audit & Compliance: Enable audit logging and retrieve audit records for compliance reporting

  • Data Management: Configure automatic pruning of historical report data to manage storage


Operational Benefits:

Instead of manually adding 300 databases (25+ hours), you can write a script that completes the task in minutes with a consistent, error-free configuration. You can also include this automation whenever a new database is created and with this, automatically added to the IBM Db2 Genius Hub Instance.

Use the IBM Db2 Genius Hub documentation to start working with the API at https://www.ibm.com/docs/en/db2-genius-hub/1.1.x?topic=working-apis.

To access the full documentation and explore interactively at, you find the link to the full documentaion in the left lower section in the Genius Hub GUI. Alternatively, use the following URL where “you-server” is the machine, running the Genius Hub Instance: http[s]://<your-server>/dbapi/api/index_enterprise.html.

3. API Exploration Tools

Before diving into automation scripts, it's essential to familiarize yourself with the available endpoints and understand how they work. Several tools exist for API exploration, including Swagger UI, Postman, and others. In this guide, we'll use Swagger UI as an example to demonstrate how to set up an interactive API testing environment.

Swagger UI: Your Interactive API Playground

Swagger UI is a powerful open-source tool that transforms API documentation into an interactive testing environment. While Genius Hub provides API documentation in ReDoc format, you can set up Swagger UI separately to get hands-on experience with the APIs before writing automation scripts.

What is Swagger UI?

Swagger UI creates an interactive web interface from an OpenAPI specification file. It allows you to test API endpoints directly in your browser with a "Try it out" button with no coding required.

Setting Up Swagger UI for Genius Hub APIs:


Step 1: Download the OpenAPI Specification

  1. Access your Genius Hub API documentation at http[s]://<your-server>/dbapi/api/index_enterprise.html

  2. Click the "Download" button at the top of the page (labeled "Download OpenAPI specification")

  3. Save the file - it will be named dbAPI_enterprise.inc.redoc.yaml


Step 2:
Set Up Swagger UI Locally

  1. Download Swagger UI from GitHub

    1. Download the Source code (zip) file (easier to extract on Windows/Mac)

    2. Alternatively, download Source code (tar.gz) if you prefer (common on Linux)

  2. Extract the downloaded file to a local directory on your computer

  3. Navigate to the dist folder within the extracted files

  4. Copy your downloaded dbAPI_enterprise.inc.redoc.yaml file into the dist folder

  5. Edit the swagger-initializer.js file to point to your spec file:

    • Open swagger-initializer.js in a text editor

    • Find the url: parameter (line 6)

      window.onload = function() {
        //<editor-fold desc="Changeable Configuration Block">
      
        // the following lines will be replaced by docker/configurator, when it runs in a docker-container
        window.ui = SwaggerUIBundle({
          url: "./dbAPI_enterprise.inc.redoc.yaml",
          dom_id: '#swagger-ui',
          deepLinking: true,
          presets: [
            SwaggerUIBundle.presets.apis,
            SwaggerUIStandalonePreset
          ],
          plugins: [
            SwaggerUIBundle.plugins.DownloadUrl
          ],
          layout: "StandaloneLayout"
        });
      
        //</editor-fold>
      };
  1. Save the file
  2. Start a local web server (required due to browser security restrictions):
    • Open Terminal and navigate to the dist folder:

      cd /path/to/swagger-ui-x.x.x/dist
    • Start Python's built-in HTTP server:
      python3 -m http.server 8000


S
tep 3: Configure Authentication

  1. In Swagger UI, click the "Authorize" button at the top

  2. First, get your access token by testing the authentication endpoint:

    1. Expand POST /dbapi/v4/auth/tokens

    2. Click "Try it out"

    3. Enter your userid and password

    4. Click "Execute" and copy the token from the response

  3. Return to "Authorize", paste your token as Bearer <your-token>, and click "Authorize"


What You Can Do with Swagger UI:

Once Swagger UI loads with your Genius Hub API specification, you can:

  • Browse all available API endpoints organized by category

  • View detailed parameter requirements for each endpoint

  • Understand request/response schemas and data structures

  • See example values and descriptions for each API operation


Best Practices:

  • Always authenticate first using the "Authorize" button

  • Start with GET requests before trying POST/PUT/DELETE

  • Test in development environments first

  • Save successful examples for automation scripts 

4. The sample Python Application

The following sections walk through a Python script that reads database connection details from a CSV file and registers them with Db2 Genius Hub via the REST API. The script covers two main steps: first, obtaining an authentication token; second, iterating over each row in the CSV file and calling the database profile endpoint to register each database in bulk.


4.
1 Generating an Authentication Token


NOTE: Before any of the automation in this guide can run, onboarding databases or pulling alerts, you need one thing first: a valid token.

Every Genius Hub API call requires authentication via a valid bearer token. You can generate a token using your Genius Hub credentials. The response provides a short-lived JWT token, which can be passed in the Authorization header of every subsequent API request. In case of long running automation scripts, token refresh needs to be handled. This has been covered in the full script in Section 6.

The endpoint:

POST /dbapi/v4/auth/tokens

Request body:

{
  "userid": "your_username",
  "password": "your_password"
}

Successful response (HTTP 200):

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Full Python Code

import requests

GENIUS_HUB_URL = "http://your-server:11100/dbapi/v4"

def get_token(userid: str, password: str) -> str:
    """Authenticate with Genius Hub and return a bearer token."""
    response = requests.post(
        f"{GENIUS_HUB_URL}/auth/tokens",
        json={"userid": userid, "password": password},
        verify=False  # Set to True and provide cert path in production
    )
    if response.status_code == 200:
        token = response.json()["token"]
        print("Authentication successful.")
        return token
    else:
        raise RuntimeError(
            f"Authentication failed: HTTP {response.status_code} — {response.text}"
        )

# Usage
token = get_token("your_username", "your_password")
print(f"Token: {token[:40]}...")  # Print first 40 chars only

Security note: Never hardcode credentials in your scripts. Use environment variables (os.environ["GH_PASSWORD"]) or a secrets manager such as HashiCorp Vault to supply them at runtime.

 

4.2 Adding a Database Connection via API


A connection profile in Db2 holds the JDBC connection details for the target database, the credentials Genius Hub uses to collect monitoring data, and any additional settings for the connection itself. Once a profile exists, Genius Hub starts monitoring that database automatically.

The endpoint:

POST /dbapi/v4/dbprofiles

Field

Description

name

Unique profile name shown in the console — choose a consistent naming convention

host

Hostname or IP of the Db2 server

port

Db2 TCP port (default 50000)

databaseName

The Db2 database name

dataServerType

DB2LUW for Linux/Unix/Windows, DB2Z for z/OS

collectionCred

Credentials used by Genius Hub to collect monitoring data — a read-only monitoring user is sufficient

operationCred

Credentials used for operational actions such as running SQL or jobs — can be the same user or a more privileged one depending on your security policy

sslConnection

Set to "true" and provide sslTrustStoreLocation and sslTrustStorePassword if your Db2 server requires an encrypted connection

comment

Optional free-text description — useful for tracking how and when profiles were created

A successful response returns HTTP 201 Created with an empty body. There might be other return codes. For example the return code “409 Conflict means a profile with that name already exists.

Full Python Code

import requests

GENIUS_HUB_URL = "http://your-server:11100/dbapi/v4"

def add_database_profile(token: str, profile: dict) -> bool:
    """Add a single database connection profile to Genius Hub.

    Returns True on success, False if the profile already exists.
    Raises RuntimeError on unexpected errors.
    """
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type":  "application/json"
    }
    response = requests.post(
        f"{GENIUS_HUB_URL}/dbprofiles",
        json=profile,
        headers=headers,
        verify=False
    )
    if response.status_code == 201:
        print(f"  ✓ Added: {profile['name']}")
        return True
    elif response.status_code == 409:
        print(f"  ⚠ Already exists: {profile['name']} — skipping")
        return False
    else:
        raise RuntimeError(
            f"  ✗ Failed to add {profile['name']}: "
            f"HTTP {response.status_code} — {response.text}"
        )

# Usage
profile = {
    "name":           "PROD_DB2_001",
    "host":           "db2-host-01.example.com",
    "port":           50000,
    "databaseName":   "MYDB",
    "dataServerType": "DB2LUW",
    "collectionCred": {
        "user":                 "db2inst1",
        "password":             "monitor_password",
        "securityMechanism":    "3",
        "encryptionAlgorithm":  "1",
        "kerberosUseCachedTGT": "false"
    },
    "operationCred": {
        "user":                 "db2inst1",
        "password":             "monitor_password",
        "securityMechanism":    "3",
        "encryptionAlgorithm":  "1",
        "kerberosUseCachedTGT": "false",
        "saveOperationCred":    "false"
    },
    "sslConnection": "false",
    "comment":       "Onboarded via REST API"
}

added = add_database_profile(token, profile)


4.3
. Adding Databases in Bulk


In order to solve the original problem of onboarding hundreds of databases, we now discuss a complete automated flow. For the
example used in this documentation, we use a list of database in a CSV file that should be added to Db2 Genius Hub. So for setup discussed in this section, you need a CSV file with configuration details of all the databases that you want to monitor with Genius Hub.

The script reads database definitions from this CSV file, authenticates, and loops through every entry.

Sample input CSV file (databases.csv):

name,host,port,databaseName,userid,password,dataServerType
PROD_DB2_001,db2-host-01.example.com,50000,MYDB,db2monitor,monpass,DB2LUW
PROD_DB2_002,db2-host-02.example.com,50000,SALESDB,db2monitor,monpass,DB2LUW
DEV_DB2_001,dev-host-01.example.com,50000,DEVDB,db2monitor,devpass,DB2LUW


The complete automation script:

import csv
import os
import requests
import urllib3
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# Disable SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# ── Configuration ──────────────────────────────────────────────────────────────
GENIUS_HUB_URL = os.environ.get("GH_URL", "http://your-server:11100/dbapi/v4")
GH_USER        = os.environ.get("GH_USER", "admin")
GH_PASSWORD    = os.environ.get("GH_PASSWORD")          # Always from environment
CSV_FILE       = "databases.csv"

# ── Create a session with retry logic ─────────────────────────────────────────
def create_session():
    """Create a requests session with retry logic and proper configuration."""
    session = requests.Session()
    
    # Configure retry strategy
    retry_strategy = Retry(
        total=3,
        backoff_factor=1,
        status_forcelist=[429, 500, 502, 503, 504],
        allowed_methods=["HEAD", "GET", "POST", "PUT", "DELETE", "OPTIONS", "TRACE"]
    )
    
    adapter = HTTPAdapter(max_retries=retry_strategy, pool_connections=10, pool_maxsize=10)
    session.mount("http://", adapter)
    session.mount("https://", adapter)
    
    return session

# ── Authentication ─────────────────────────────────────────────────────────────
def get_token(session: requests.Session, userid: str, password: str) -> str:
    response = session.post(
        f"{GENIUS_HUB_URL}/auth/tokens",
        json={"userid": userid, "password": password},
        verify=False,
        timeout=30
    )
    if response.status_code == 200:
        return response.json()["token"]
    raise RuntimeError(f"Authentication failed: HTTP {response.status_code}")

# ── Build profile payload from CSV row ────────────────────────────────────────
def build_payload(row: dict) -> dict:
    # Support both 'userid'/'password' and 'collectionUser'/'collectionPassword' column names
    user = row.get("collectionUser") or row.get("userid", "")
    password = row.get("collectionPassword") or row.get("password", "")
    
    cred = {
        "user":                 user,
        "password":             password,
        "securityMechanism":    "3",
        "encryptionAlgorithm":  "1",
        "kerberosUseCachedTGT": "false"
    }
    return {
        "name":           row["name"],
        "host":           row["host"],
        "port":           str(row["port"]),  # Send port as string
        "databaseName":   row["databaseName"],
        "dataServerType": row.get("dataServerType", "DB2LUW"),
        "collectionCred": cred,
        "operationCred":  {**cred, "saveOperationCred": "false"},
        "sslConnection":  row.get("ssl", "false"),
        "comment":        "Onboarded via REST API"
    }

# ── Add a single database profile ──────────────────────────────────────────────
def add_profile(session: requests.Session, token: str, row: dict) -> str:
    """Returns 'added', 'exists', or 'error:<message>'."""
    headers = {"Authorization": f"Bearer {token}"}
    r = session.post(
        f"{GENIUS_HUB_URL}/dbprofiles",
        json=build_payload(row), headers=headers, verify=False, timeout=30
    )
    if r.status_code == 201:
        return "added"
    elif r.status_code == 409:
        return "exists"
    else:
        return f"error:HTTP {r.status_code} — {r.text[:120]}"

# ── Main onboarding loop ───────────────────────────────────────────────────────
def main():
    if not GH_PASSWORD:
        raise EnvironmentError("Set the GH_PASSWORD environment variable before running.")

    print(f"Connecting to Genius Hub: {GENIUS_HUB_URL}")
    
    # Create session for connection pooling
    session = create_session()
    
    try:
        token = get_token(session, GH_USER, GH_PASSWORD)
        print("Authentication successful.\n")
    except Exception as e:
        print(f"ERROR: Failed to authenticate: {e}")
        return

    counts = {"added": 0, "exists": 0, "error": 0}
    errors = []

    with open(CSV_FILE, newline="") as f:
        reader = csv.DictReader(f)
        rows   = list(reader)

    print(f"Processing {len(rows)} databases from {CSV_FILE}...\n")

    for i, row in enumerate(rows, 1):
        name   = row.get("name", f"row_{i}")
        result = add_profile(session, token, row)

        if result == "added":
            counts["added"] += 1
            print(f"  [{i:>4}/{len(rows)}] ✓  Added   : {name}")
        elif result == "exists":
            counts["exists"] += 1
            print(f"  [{i:>4}/{len(rows)}] ⚠  Skipped : {name} (already registered)")
        else:
            counts["error"] += 1
            errors.append((name, result))
            print(f"  [{i:>4}/{len(rows)}] ✗  Failed  : {name} — {result}")

    # ── Summary ────────────────────────────────────────────────────────────────
    print("\n" + "="*60)
    print("  Onboarding Complete")
    print("="*60)
    print(f"  Total processed : {len(rows)}")
    print(f"  Added           : {counts['added']}")
    print(f"  Already existed : {counts['exists']}")
    print(f"  Errors          : {counts['error']}")

    if errors:
        print("\n  Failed profiles:")
        for name, reason in errors:
            print(f"    • {name}: {reason}")

    print("="*60)

if __name__ == "__main__":
    main()


Running the script:

# Set credentials as environment variables — never in the script
export GH_URL="http://your-genius-hub-server:11100/dbapi/v4"
export GH_USER="admin"
export GH_PASSWORD="your_password"

python3 onboard_databases.py


What to customise before running:

  • CSV_FILE: Point to your actual CSV file path, or extend the script to accept it as a command-line argument.

  • DRIVER_TYPE: Set to "2" for Type-2 (local client) connections if required by your environment.

  • verify=False: Replace with verify="/path/to/ca-bundle.crt" once your Genius Hub server uses a trusted TLS certificate.

For very large onboarding batches (1000+ databases): Consider splitting your CSV into chunks and running in parallel with Python's concurrent.futures.ThreadPoolExecutor. The Genius Hub API supports concurrent requests, so this can reduce a 1000-database onboarding from minutes to seconds.

5. What Else Can You Automate?

Onboarding databases is just the beginning, the same API setup can give you programmatic access to everything Genius Hub monitors. The /alerts endpoint is a good illustration of this. It gets open alerts from every registered database in a single response, each tagged with its connection profile.

The endpoint:

GET /dbapi/v4/alerts


Required headers:

Header

Value

Description

Authorization

Bearer <token>

Your authentication token

x-db-profile

*all*

Returns alerts across all registered databases

Sample Success response (HTTP 200):

{
    "warningAlertCount": <warning_count>,
    "criticalAlertCount": <critical_count>,
    "count": <total_alerts>,
    "infoAlertCount": <info_count>,
    "resources": [
        {
            "severity": "<alert_severity>",
            "notification_type": "alert",
            "alertAnalysisDesc": "<alert_analysis_description>",
            "read": false,
            "start_timestamp": <alert_start_timestamp>,
            "type": "<alert_type>",
            "end_timestamp": <alert_end_timestamp>,
            "name": "<connection_profile_name>",
            "id": "<alert_id>",
            "category": "<alert_category>",
            "actions": [
                {
                    "actionDescription": "<alert_action_description>",
                    "actionLabel": ""
                }
            ],
            "entity": "0",
            "alertDetails": {},
            "group": "<alert_group>"
        }
    ]
}

The API returns a JSON array of alert objects. Each entry includes the name field, so alert can be associated with its origin database connection profile. The response has a breakdown of alert counts by severity at the top level, namely, criticalAlertCount, warningAlertCount, infoAlertCount. Each alert in resources also carries its category, group, and a detailed alertAnalysisDesc along with recommended actions, which means the data is actionable straight out of the API response with no need for an additional lookup.

Full Python Code

In a large environment with hundreds of databases, the total number of alerts can be substantial. So, rather than fetching all alerts and then filtering, Genius Hub gives you a dedicated /alerts/filter endpoint that does the heavy lifting at the server-side. You can pass severity, group, filter, and sort as query parameters and get back exactly what you need.

The example below pulls only open critical alerts across all databases, sorted with the most recent first.

import requests
from datetime import datetime

GENIUS_HUB_URL = "http://your-server:11100/dbapi/v4"

def get_critical_alerts(token: str) -> list:
    """Fetch open critical alerts across all databases using server-side filtering."""
    headers = {
        "Authorization": f"Bearer {token}",
        "x-db-profile":  "*all*"
    }
    params = {
        "severity": "critical",
        "filter":   "isOpen",
        "sort":     "-severity,+started",  # Most severe first, then oldest first
        "limit":    1000
    }
    response = requests.get(
        f"{GENIUS_HUB_URL}/alerts/filter",
        headers=headers,
        params=params,
        verify=False
    )
    if response.status_code == 200:
        alerts = response.json()
        if isinstance(alerts, list):
            return alerts
        return alerts.get("resources", [])
    else:
        raise RuntimeError(
            f"Failed to retrieve alerts: HTTP {response.status_code} — {response.text}"
        )

def print_critical_alerts(alerts: list):
    """Print critical alerts grouped by database."""
    if not alerts:
        print("No critical alerts across any monitored database.")
        return

    print(f"\nCritical Alerts — {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("="*60)
    print(f"{len(alerts)} critical alert(s) found\n")

    by_profile = {}
    for alert in alerts:
        profile = alert.get("profile_name", "unknown")
        by_profile.setdefault(profile, []).append(alert)

    for profile, db_alerts in sorted(by_profile.items()):
        print(f"  {profile} ({len(db_alerts)} critical alert(s))")
        for a in db_alerts:
            name    = a.get("alert_name", a.get("name", "—"))
            message = a.get("message", "")[:80]
            print(f"    [CRITICAL] {name}: {message}")
    print("="*60)

# Usage
alerts = get_critical_alerts(token)
print_critical_alerts(alerts)


Taking the Data Further

Genius Hub already gives you this consolidated view out of the box through its console, however if your operations team wants to integrate Db2 alerts into their existing observability tool, the API makes it just as easy.

Whether that's a Datadog event, a Splunk HEC endpoint, or a webhook into ServiceNow, a POST request to your platform’s ingestion API, piped with the alert data, is all it takes to bring Db2 alert visibility.

6. Final Thought

The Genius Hub REST API surface goes well beyond what we have covered here. The intention of this Blog is to introduce the basic workflow, consisting of authentication, setting the right headers and parsing the JSON response.

This main steps can be used as a base for further enhancements in the uses and as a starting point for all use cases you may have in mind.

0 comments
17 views

Permalink