Software and Firmware Deployment

IT EngineersDevelopers

Getting Started

Core Concepts

Deploy installation files and firmware based on target systems and versions

Software and firmware files are used across many environments, including servers, branch systems, production equipment, and edge devices.

Software and firmware deployment prepares installation packages, build artifacts, and firmware files, then configures deployment tasks based on the target systems and versions to apply.

You can configure deployment flows suited to the operating environment, such as deploying one file to multiple systems or applying different files and versions to different system groups.

Deployment Configuration

text
Deployment Files
    │
    ▼
Configure Version Criteria
    │
    ▼
Select Target Systems
    │
    ├────────→ Server Group
    ├────────→ Branch Systems
    └────────→ Edge Devices
                    │
                    ▼
                 Check Results

This process lets you manage deployment files, target systems, and application criteria as a single flow.

Deployment Flow

Continue from file preparation through application to target systems and result confirmation

A deployment task starts by preparing the installation file or firmware and configuring the systems and versions to which it will be applied.

When the deployment task runs according to the specified conditions, files are transferred to each target system and you can review progress and file application results by system.

① Prepare Deployment File

② Configure Target Systems

③ Set Version and Execution Criteria

④ Deploy Files by Target

⑤ Check Application Results

When needed, you can rerun deployment for a specific system or system group.

Deployment Benefits

Manage file deployment and version control across multiple systems as a single flow

Software and firmware deployment across multiple systems requires managing the deployment file, targets, version, and execution results together.

Software and firmware deployment lets you organize system-level deployment tasks into a single management flow and identify which files were deployed to which targets.

CategoryIndividual System ManagementDeployment Flow
Deployment TargetsCheck targets by systemManage by system and group
Deployment FilesCheck application targets by fileConfigure together with the deployment task
Version ApplicationCheck application status by systemDeploy according to version criteria
Execution ResultsReview each system individuallyReview results for all targets together
RedeploymentSelect required systems againRerun by target or group

This lets you manage the entire operational flow from software and firmware deployment through target-specific result confirmation.

IT Engineers

Deployment Files

Prepare installation packages and firmware files according to deployment criteria

First, prepare the installation packages, build artifacts, or firmware files to use for deployment.

A file can be used for multiple targets within one deployment task, and different files can also be assigned by system group according to the operating environment.

For example, the following file types can be configured as deployment targets.

File TypeExample Use
Installation PackageApplication installation file
Build ArtifactLatest build file and deployment package
FirmwareFirmware for systems and edge devices
Update FileUpdate file to apply to an existing environment

After preparing the deployment files, configure the systems and groups to which they will be applied in the next step.

Target Configuration

Configure servers, branches, and edge devices by deployment group and individual system

Deployment targets can be configured as individual systems or grouped into a single target group.

For example, configure targets according to operational criteria as headquarters servers, nationwide branch systems, specific production equipment, or edge device groups.

text
                Deployment Targets
                    │
        ┌───────────┼───────────┐
        ▼           ▼           ▼
     Server Group    Branch Group    Edge Group
        │           │           │
       System A       System D       System G
       System B       System E       System H
       System C       System F       System I

This lets you select multiple systems in one deployment task or define the deployment scope for a specific group only.

Deployment Criteria

Set file versions and execution conditions by system

After configuring the targets, define which files should be deployed and according to which criteria.

Connect the deployment file version to the target systems and configure execution conditions to run immediately, on a schedule, or after another task completes.

Criteria to Configure

Configuration ItemConfiguration
Deployment FileSpecify the installation package or firmware
Applied VersionSpecify the file version to deploy to target systems
Target ScopeSelect all systems, a group, or individual systems
Execution ConditionsRun immediately, on a schedule, or after another task completes
File PathSet the storage or application location on the target system

For example, you can deploy the latest firmware to a specific system group after it is prepared, or deploy build results to a designated server after the build task completes.

Multi-Target Deployment

Transfer files to multiple target systems with a single deployment task

After setting deployment criteria, configure a multi-target deployment flow that transfers one file to multiple target systems.

Connect one deployment source to multiple target systems in the Flow Canvas to deploy the same file to servers, branches, edge devices, and other environments.

text
                  Deployment File
                      │
                      ▼
                 Deployment Task
            ┌─────────┼─────────┐
            ▼         ▼         ▼
         Server      Branch     Edge
            │         │         │
            ▼         ▼         ▼
         Confirm Completion   Confirm Completion   Confirm Completion

Target systems can be processed together or selected by group and individual system according to operational criteria.

Result Management

Review application status by target and rerun deployment for required systems

When a deployment task runs, use Runs and task details to review the overall deployment status and results by target.

During review, you can check each system's progress status, processed files, execution time, and other details together.

Deployment Result Flow

text
Run Deployment
    │
    ▼
Check Overall Task Status
    │
    ├── Completed
    │      │
     │      └── Check Application Result by Target
    │
    ├── Running
    │      │
     │      └── Check Progress and Processing Status
    │
     └── Review Required
           │
           ▼
        Review Detailed Result
           │
           ▼
        Select Target System
           │
           ▼
        Rerun Deployment Task

Review ItemDetails
Target SystemServers and systems where files were deployed
Progress StatusCurrent processing status of the deployment task
File ResultFile application result by target system
Execution TimeDeployment start and completion time
Redeployment TargetSystem or group to rerun

When you need to review the deployment result for a specific system again, rerun the required task based on that target or system group.

Developers

Deploy one artifact to multiple systems and aggregate application results by system

Integration Preparation

Prepare shared request code and status values

import os
import requests

BASE_URL = os.getenv("INNORIX_BASE_URL", "https://app.innorix.com").rstrip("/")
TOKEN = os.environ["INNORIX_ACCESS_TOKEN"]
WORKSPACE_ID = os.getenv("INNORIX_WORKSPACE_ID")   # optional; falls back to the current workspace

STATUS_COMPLETE = 2
TERMINAL = {2, 4, 5, 9, 99}          # complete / error / cancelled / partial / failed
NOT_SUCCEEDED = {4, 5, 9, 99}


def api(method, path, body=None, params=None):
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {TOKEN}",
    }

    if WORKSPACE_ID:
        headers["x-workspace-id"] = WORKSPACE_ID

    response = requests.request(
        method, BASE_URL + path,
        headers=headers, json=body, params=params, timeout=30,
    )

    payload = response.json() if response.content else {}

    if not response.ok:
        raise RuntimeError(payload.get("message") or f"HTTP {response.status_code}")

    return payload.get("data")


def is_terminal(detail):
    return detail.get("isTerminal", detail.get("status") in TERMINAL)

Determine the transfer status using the values below. There are five terminal states, and the successful state is Complete (2).

Status ValueMeaningTerminal
2CompleteYes
4ErrorYes
5CancelledYes
9Partially CompleteYes
99FailedYes
1 · 6 · 12 · 13Started · Transferring · Synchronizing · ReceivingNo

Configure Deployment Targets

Define device groups as a list and confirm their identifiers

Manage deployment targets as a list. When working with system names, convert them to identifiers first.

def resolve_device(name):
    result = api("GET", "/api/devices/resolve", params={"name": name}) or {}
    devices = result.get("devices") or []
    count = result.get("matchCount", len(devices))

    if count != 1 or not devices:
        raise RuntimeError(f"{name}: {count} matches")

    return devices[0]["deviceId"]


GROUPS = {
    "server": ["srv-01", "srv-02", "srv-03"],
    "branch": ["branch-seoul", "branch-busan"],
    "edge":   ["edge-line-01", "edge-line-02"],
}

RESOLVED = {
    group: [resolve_device(name) for name in names]
    for group, names in GROUPS.items()
}

You can also filter the full system list using conditions.

result = api("GET", "/api/devices", params={"page": 1, "size": 200}) or {}

edge_devices = [d["deviceId"] for d in result.get("devices") or []
                if d["name"].startswith("edge-")]

The device list is returned in the data.devices array.

Design Version Paths

Make the deployment file version visible in the path

Record which version was applied where in the path.

def package_path(product, version):
    return f"/release/{product}/{version}"


def target_path(product, version):
    return f"/opt/{product}/{version}"


PRODUCT, VERSION = "app", "2.14.0"

Keeping a separate folder for each version leaves previous versions available, making rollback easier when problems occur. If everything is overwritten in a single path, there is no version to roll back to.

Multi-Target Deployment

Send one file to multiple systems

A single transfer handles one target system. Create a transfer for each target and store the returned monitorId by system to track progress and results.

def deploy(source, targets, product, version, target_paths=None):
    src = package_path(product, version)

    # pass a list when targets need different paths; the order must match
    paths = target_paths or [target_path(product, version)] * len(targets)

    return {
        device: api("POST", "/api/transfers/manual", {
            "sourceDevice": source,
            "targetDevice": device,
            "targetPath": path,
            "sourcePaths": [src],
            "sendAllFolder": True,
            "checkIntegrity": True,
            "transferOptions": {"target-action": "overwrite"},
        })["monitorId"]
        for device, path in zip(targets, paths)
    }


transfers = deploy("device-build-01", RESOLVED["edge"], PRODUCT, VERSION)

Within a version folder, the same file is usually sent again, so use overwrite. With numbering, copies accumulate every time you redeploy.

Enable integrity verification. If firmware is applied in a corrupted state, the system may fail to boot.

If the environment shares field network links, apply a rate limit so other operations are not affected.

"transferOptions": {
  "target-action": "overwrite",
  "limitRate": 20480
}

The unit for limitRate is KB/s.

Aggregate Results

Collect application status by system and review it together

def wait(monitor_id, timeout=3600, interval=3):
    deadline = time.time() + timeout

    while time.time() < deadline:
        detail = api("GET", f"/api/transfers/{monitor_id}")

        if is_terminal(detail):
            return detail

        time.sleep(interval)

    raise TimeoutError(monitor_id)


def failed_files(monitor_id):
    result = api("GET", f"/api/transfers/{monitor_id}/files", params={
        "state": "any", "size": 500,
    }) or {}

    return [r for r in (result.get("children") or [])
            if r.get("status") in NOT_SUCCEEDED]


def retry_failed(monitor_id):
    rows = failed_files(monitor_id)

    if not rows:
        return 0

    api("POST", f"/api/transfers/{monitor_id}/retry", {
        "filesRetry": [
            {"filePath": r["sourceFilePath"], "isDir": bool(r.get("isFolder"))}
            for r in rows
        ]
    })

    return len(rows)

Even if one system fails, continue checking the others so you know how far deployment has progressed.

def deploy_report(transfers, timeout=3600):
    results = {}

    for device, monitor_id in transfers.items():
        try:
            results[device] = wait(monitor_id, timeout=timeout)
        except TimeoutError:
            results[device] = {"status": None}

    succeeded = [d for d, r in results.items()
                 if r.get("status") == STATUS_COMPLETE]
    failed = [d for d in results if d not in succeeded]

    return succeeded, failed, results


succeeded, failed, results = deploy_report(transfers)

print(f"{len(succeeded)} succeeded / {len(failed)} failed")

for device in failed:
    detail = results[device]
    print(f"  {device:20} {detail.get('statusName') or detail.get('status')}")
Review ItemDetails
statusTransfer status by system
percentProgress
fileCount · totalSizeApplied file count and size
endDateCompletion time

Redeploy Failed Systems

Skip successful systems and redeploy only failed targets

Rerunning everything transfers files again even to systems where deployment already succeeded. Select only the failed targets and rerun them.

for device in failed:
    monitor_id = transfers[device]
    rows = failed_files(monitor_id)

    if rows:
        # reached the device, but some files failed
        print(f"{device}: retried {retry_failed(monitor_id)} files")
    else:
        # no per file record means the transfer never started
        state = api("GET", f"/api/devices/{device}/connectivity") or {}
        print(f"{device}: transfer never started - connected {state.get('isConnected')}"
              f" ({state.get('stateLabel')})")

If there is no file-level failure record, check the system connection first. Rerun deployment after the connection is restored.

if still_offline:
    retry_transfers = deploy("device-build-01", recovered, PRODUCT, VERSION)
    _, still_failed, _ = deploy_report(retry_transfers)

Review Deployment History

Check which version was applied to which system and when

from datetime import datetime, timedelta, timezone


def paginate(path, params=None, limit=200, max_pages=50):
    query = dict(params or {})
    query["limit"] = limit
    cursor = None

    for _ in range(max_pages):
        if cursor:
            query["cursor"] = cursor

        result = api("GET", path, params=query) or {}

        for record in result.get("data") or []:
            yield record

        pagination = result.get("pagination") or {}

        if not pagination.get("hasMore"):
            return

        cursor = pagination.get("nextCursor")

        if not cursor:
            return


end = datetime.now(timezone.utc)
fmt = "%Y-%m-%dT%H:%M:%SZ"

for row in paginate(f"/api/devices/{device_id}/transfer-history", params={
    "startDate": (end - timedelta(days=30)).strftime(fmt),
    "endDate": end.strftime(fmt),
}):
    print(row.get("startDate"), row.get("statusName"), row.get("monitorId"))

Recording the deployment identifier and version together in the application connects the history with the version.

db.insert("deployments", {
    "product": PRODUCT,
    "version": VERSION,
    "device": device,
    "monitorId": transfers[device],
    "result": "done" if device in succeeded else "failed",
})
Review ItemDetails
Deployment FileTransferred package and version
TargetsSystems and groups
ResultSuccess and failure by system
RedeploymentTargets and results rerun
HistoryRecent deployment history by system