Skip to main content

Automated JUNOS package management tool for Juniper Networks devices

Project description

junos-ops

PyPI version CI Python

日本語版 / Japanese

A Python CLI to automate Juniper/JUNOS operations over NETCONF: model-aware upgrade, rollback, reboot, config push, and RSI/SCF collection.

RSI/SCF? RSI = request support information (the JTAC-style support snapshot), SCF = show configuration | display set. Collected files are saved with .rsi / .scf extensions — hence the shorthand used throughout this tool.

Features

  • Automatic device model detection and package mapping
  • Safe package copy via SCP with checksum verification
  • Pre-install package validation
  • Rollback support (model-specific handling for MX/EX/SRX)
  • Scheduled reboot with automatic config-drift detection and re-install
  • Parallel RSI (request support information) / SCF (show configuration | display set) collection
  • Pre-flight check subcommand: NETCONF reachability, local firmware checksum (device-less), and remote firmware checksum in one unified table
  • Arbitrary CLI command execution across hosts (show) with RpcTimeoutError retry
  • Configuration push with commit confirmed safety and post-commit health checks (ping, uptime NETCONF probe, or any CLI command)
  • Jinja2 template support for per-host configuration generation (details)
  • Tag-based host filtering (--tags) for AND-matched multi-site workflows
  • Local firmware directory (lpath) with ~ expansion
  • Dry-run mode (--dry-run) for pre-flight verification
  • Machine-readable JSON output (--json) for piping into jq / monitoring / Ansible
  • Parallel execution via ThreadPoolExecutor (--workers N)
  • INI-based host and package management

Table of Contents

Installation

Homebrew (macOS)

brew install shigechika/tap/junos-ops

Debian / Ubuntu (.deb)

Pre-built packages for Ubuntu 24.04 (Noble) are available on the GitHub Releases page. The package installs a self-contained Python virtualenv at /opt/venvs/junos-ops/ with junos-ops symlinked to /usr/bin/:

sudo apt install ./junos-ops_*~noble.deb

RHEL / Rocky Linux / AlmaLinux (.rpm)

Pre-built packages for RHEL/Rocky/AlmaLinux 9 are available on the GitHub Releases page. Python 3.12 is required:

sudo dnf install python3.12
sudo rpm -ivh junos-ops-*-1.el9.x86_64.rpm

pip

pip install junos-ops

To upgrade to the latest version:

pip install junos-ops --upgrade

Development Setup

git clone https://github.com/shigechika/junos-ops.git
cd junos-ops
python3 -m venv .venv
. .venv/bin/activate
pip install -e ".[test]"

Dependencies

Tab Completion (optional)

pip install junos-ops[completion]
eval "$(register-python-argcomplete junos-ops)"

Add the eval line to your shell profile (~/.bashrc or ~/.zshrc) to enable it permanently.

Installing pip3 (if not available)

OS-specific instructions
  • Ubuntu/Debian

    sudo apt install python3-pip
    
  • CentOS/RedHat

    sudo dnf install python3-pip
    
  • macOS

    brew install python3
    

Configuration File (config.ini)

An INI-format configuration file that defines connection settings and model-to-package mappings.

The configuration file is searched in the following order (-c / --config can override):

  1. ./config.ini in the current directory
  2. ~/.config/junos-ops/config.ini (XDG_CONFIG_HOME)

Logging Configuration (logging.ini)

An optional logging.ini file can be used to customize log output (e.g., suppress verbose paramiko/ncclient messages). The file is searched in the same order as config.ini:

  1. ./logging.ini in the current directory
  2. ~/.config/junos-ops/logging.ini (XDG_CONFIG_HOME)

If neither is found, the default logging configuration (INFO level to stdout) is used.

DEFAULT Section

Defines global connection settings and model-to-package mappings shared by all hosts.

[DEFAULT]
id = exadmin          # SSH username
pw = password         # SSH password
sshkey = id_ed25519   # SSH private key file
port = 830            # NETCONF port
hashalgo = md5        # Checksum algorithm
rpath = /var/tmp      # Remote path
# ssh_config = ~/.ssh/config   # OpenSSH config (ProxyCommand etc.); if unset, PyEZ auto-picks up ~/.ssh/config
# lpath = ~/firmware   # Local firmware directory (~ expanded, default: current directory)
# huge_tree = true    # Allow large XML responses
# RSI_DIR = ./rsi/    # Output directory for RSI/SCF files
# DISPLAY_STYLE = display set   # SCF output style (default: display set)
# DISPLAY_STYLE =               # Empty for stanza format (show configuration only)

# model.file = package filename
# model.hash = checksum value
EX2300-24T.file = junos-arm-32-18.4R3-S10.tgz
EX2300-24T.hash = e233b31a0b9233bc4c56e89954839a8a

The model name must match the model field automatically retrieved from the device.

Host Sections

Each section name becomes the hostname. DEFAULT values can be overridden per host.

[rt1.example.jp]             # Section name is used as the connection hostname
tags = tokyo, core           # Tag-based host filtering (--tags)
[rt2.example.jp]
host = 192.0.2.1             # Override connection target with IP address
tags = osaka, core
[sw1.example.jp]
id = sw1                     # Override SSH username
sshkey = sw1_rsa             # Override SSH key
ssh_config = ~/.ssh/config.lab   # Per-host OpenSSH config (e.g. behind a bastion)
tags = tokyo, access
[sw2.example.jp]
port = 10830                 # Override port
[sw3.example.jp]
EX4300-32F.file = jinstall-ex-4300-20.4R3.8-signed.tgz   # Different version for this host
EX4300-32F.hash = 353a0dbd8ff6a088a593ec246f8de4f4

Usage

junos-ops <subcommand> [options] [hostname ...]

Subcommands

Subcommand Description
upgrade [--unlink] Copy and install package (--unlink for low-flash devices, see below)
copy Copy package from local to remote
install [--unlink] Install a previously copied package (--unlink for low-flash devices, see below)
rollback Rollback to the previous version
version Show running/planning/pending versions and reboot schedule
reboot --at YYMMDDHHMM Schedule a reboot at the specified time
ls [-l] List files on the remote path
show COMMAND [--retry N] / show -f FILE Run an arbitrary CLI command (or file of commands) across devices
check [--connect|--local|--remote|--all] [--model M] Pre-flight checks: NETCONF reachability, local/remote firmware checksum
config -f FILE Push a set command file (see docs/config.md for --confirm, --timeout, --no-confirm, --no-commit, --health-check, --no-health-check)
rsi Collect RSI/SCF in parallel
(none) Show device facts

Common Options

Option Description
hostname Target hostname(s) (defaults to all hosts in config file)
-c, --config CONFIG Config file path (default: config.ini or ~/.config/junos-ops/config.ini)
-n, --dry-run Test run (connect and display messages only, no execution)
-d, --debug Debug output
--force Force execution regardless of conditions
--json Emit machine-readable JSON instead of human-readable text. One JSON object per host per line (JSONL); logs are routed to stderr so stdout stays pure JSON. Pipe to jq -s to slurp into an array. See "JSON Output" below.
--tags TAG[,TAG...] Filter hosts by tags. Comma-separates AND together inside one value; repeating --tags ORs groups. Combined with explicit hostnames, the tag filter and hostname list intersect. See "Tag-based Host Filtering" below.
--exclude-tags TAG[,TAG...] Drop hosts whose tags match. Same AND/OR grammar as --tags (comma = AND within a group, repeat to OR groups). Applied after --tags; usable standalone to subtract a subset from the default "all hosts" selection.
--workers N Parallel workers (default: 1 for upgrade, 20 for rsi)
--version Show program version

JSON Output

Pass --json to any subcommand to get machine-readable output. Each host emits one JSON object on its own line (JSON Lines / JSONL), which composes cleanly with parallel --workers N runs:

$ junos-ops version --json rt1.example.jp rt2.example.jp
{"hostname": "rt1.example.jp", "ok": true, "model": "MX240", "running": "22.4R3-S6.5", ...}
{"hostname": "rt2.example.jp", "ok": true, "model": "EX2300-24T", "running": "22.4R3-S6.5", ...}
  • Logs (including config's real-time commit progress) and startup diagnostics (unreadable config, no matching hosts) go to stderr, so 2>/dev/null or piping stdout alone yields valid JSON only. Check the exit code to detect a startup failure (stdout is then empty).
  • A host that fails to connect or errors mid-run still emits a line — {"hostname": ..., "ok": false, "error": ..., "error_message": ...} — so a consumer never silently misses a host.
  • Slurp the stream into a single array with jq -s: junos-ops version --json | jq -s '.'
  • check --json tags each line with "check": "local" (model-keyed inventory rows) or "check": "host" (per-host rows).

Workflow

CLI Architecture Overview

All subcommands share the same execution pipeline: read the config file, determine target hosts (optionally filtered by --tags), then dispatch each host to a worker thread via ThreadPoolExecutor. The --workers N option controls parallelism — defaulting to 1 for upgrade operations (safe sequential execution) and 20 for RSI collection (I/O-bound, benefits from concurrency). Each worker establishes its own NETCONF session, so hosts are processed independently with no shared state.

flowchart TD
    A[junos-ops CLI] --> B[Read config.ini]
    B --> C[Determine target hosts]
    C --> D{Subcommand}
    D --> E[upgrade / copy / install]
    D --> F[version / rollback / reboot]
    D --> G[config / show / ls]
    D --> H[rsi]
    D --> I["(none) → facts"]
    E & F & G & H & I --> J["ThreadPoolExecutor<br/>--workers N"]
    J --> K["NETCONF / SCP<br/>per host"]
    K --> L[Results]

JUNOS Upgrade Workflow

A firmware upgrade follows a four-step sequence designed to minimize risk. First, dry-run verifies connectivity, package availability, and checksum without making changes. Then upgrade copies and installs the package. version confirms the pending version matches expectations before scheduling the reboot. The reboot is scheduled separately so you can choose a maintenance window. If anything goes wrong, rollback reverts to the previous firmware at any point before reboot.

flowchart TD
    A["1. dry-run<br/>junos-ops upgrade -n"] --> B["2. upgrade<br/>junos-ops upgrade"]
    B --> C["3. version<br/>junos-ops version"]
    C --> D["4. reboot<br/>junos-ops reboot --at"]
    D -.->|"if problems"| E["rollback<br/>junos-ops rollback"]
1. Pre-flight check with dry-run
   junos-ops upgrade --dry-run hostname

2. Copy and install with upgrade
   junos-ops upgrade hostname

3. Verify version
   junos-ops version hostname

4. Schedule reboot
   junos-ops reboot --at 2506130500 hostname

Use rollback to revert to the previous version if problems occur.

Upgrade Internal Flow

The upgrade subcommand runs multiple safety checks before and during the update process. It first compares the running version against the target — skipping entirely if already up to date. If a different pending version exists, it rolls that back before proceeding. The copy phase frees disk space (storage cleanup + snapshot delete on EX/QFX), then transfers the package via safe_copy with checksum verification to detect corruption. Before installing, it clears any existing reboot schedule and saves the rescue config as a recovery baseline. Finally, sw.install() validates the package integrity on the device before applying it.

flowchart TD
    A[NETCONF connect] --> B{"Running version<br/>= target?"}
    B -->|yes| C([Skip — already up to date])
    B -->|no| D{"Pending version<br/>exists?"}
    D -->|no| E[copy]
    D -->|yes| F{Pending ≥ target?}
    F -->|yes, no --force| C
    F -->|no / --force| G[Rollback pending version]
    G --> E

    subgraph copy ["copy()"]
        E --> H[Storage cleanup]
        H --> I["Snapshot delete<br/>(EX/QFX only)"]
        I --> J["safe_copy via SCP<br/>+ checksum verification"]:::safe
    end

    J --> K[Clear reboot schedule]
    K --> L[Save rescue config]:::safe
    L --> M["sw.install()<br/>validate + checksum"]:::install
    M --> N([Done — reboot when ready])

    classDef safe fill:#d4edda,stroke:#28a745,color:#000
    classDef install fill:#cce5ff,stroke:#007bff,color:#000

Reboot Safety Flow

Before scheduling a reboot, reboot automatically checks whether the configuration was modified after the firmware install. If changes are detected, it re-saves the rescue config and re-installs with validation to ensure the new firmware is compatible with the current config.

flowchart TD
    A[NETCONF connect] --> B{"Existing reboot<br/>schedule?"}
    B -->|no| D
    B -->|yes| C{--force?}
    C -->|no| B2([Skip — keep existing schedule])
    C -->|yes| CL[Clear existing schedule] --> D

    D{"Pending version<br/>exists?"} -->|no| SCH
    D -->|yes| E[Get last commit time]
    E --> F[Get rescue config time]
    F --> G{"Config modified<br/>after install?"}
    G -->|no| SCH
    G -->|yes| H[Re-save rescue config]:::warned
    H --> I["Re-install firmware<br/>(validate + checksum)"]:::install
    I -->|success| SCH
    I -->|failure| ERR([Abort — do not reboot]):::errstyle

    SCH["Schedule reboot at<br/>--at YYMMDDHHMM"]:::safe

    classDef safe fill:#d4edda,stroke:#28a745,color:#000
    classDef install fill:#cce5ff,stroke:#007bff,color:#000
    classDef warned fill:#fff3cd,stroke:#ffc107,color:#000
    classDef errstyle fill:#f8d7da,stroke:#dc3545,color:#000

Config Push Workflow

The config subcommand uses a safe commit flow: commit confirmed (auto-rollback timer) → health checkcommit (permanent). If the health check fails, the final commit is withheld and JUNOS automatically rolls back when the timer expires.

See docs/config.md for full details including health check options (uptime, ping, CLI commands), commit confirmed flow, --no-confirm, --no-commit, and parallel execution.

1. Preview changes with dry-run
   junos-ops config -f commands.set --dry-run hostname

2. Apply changes
   junos-ops config -f commands.set hostname

3. Apply with NETCONF health check (no ping dependency)
   junos-ops config -f commands.set --health-check uptime hostname

Tag-based Host Filtering

Use --tags to target hosts by tags defined in config.ini. The flag combines two operators so you can build almost any selection:

  • AND within a group: comma-separated tags in one --tags value require the host to carry all of them (--tags tokyo,core → hosts tagged both tokyo AND core).
  • OR between groups: repeat --tags to add another group. A host matches if it satisfies any group (--tags main --tags backup → hosts tagged either main or backup).
  • AND with a hostname list: when explicit hostnames are also given, the tag filter and the hostname list intersect — only hostnames that also satisfy the tag filter are targeted.

In logical terms: (--tags group₁) OR (--tags group₂) OR … filters the host set, and [hostname …] further restricts that set to the listed names.

History: v0.16.3 and earlier treated --tags + hostnames as union. v0.16.4 switched to intersection so --tags reads as a safety filter ("narrow further by name"). v0.16.6 added repeatable --tags for OR between groups — previously the last --tags occurrence silently replaced earlier ones.

# All hosts tagged "tokyo"
junos-ops version --tags tokyo

# Hosts tagged both "tokyo" AND "core"
junos-ops version --tags tokyo,core

# Hosts tagged "main" OR "backup"
junos-ops check --remote --tags main --tags backup

# (tokyo AND core) OR access — any host that is a tokyo core router
# or carries the access tag.
junos-ops version --tags tokyo,core --tags access

# Among "backup"-tagged hosts, target only these two (tag filter +
# hostname list = intersection)
junos-ops copy --tags backup rt1.example.jp rt2.example.jp

Excluding hosts with --exclude-tags

--exclude-tags removes hosts from the selection using the same grammar as --tags. It runs after --tags and the hostname intersection, so it acts as a final "drop these" pass.

  • --exclude-tags a,b drops hosts tagged with both a and b (AND within a group).
  • Repeating the flag ORs groups, so --exclude-tags a --exclude-tags b drops hosts tagged with a or b.
  • --exclude-tags may be used on its own; without --tags or a hostname list it subtracts from the default "all sections" set.
  • If every candidate host is dropped, junos-ops exits with an error instead of silently no-op'ing.
# All hosts tagged "main" except SRX345 boxes
junos-ops check --remote --tags main --exclude-tags srx345

# Run against every host except the lab tier
junos-ops version --exclude-tags lab

# Drop SRX345 OR EOL hosts from the main set
junos-ops check --remote --tags main \
                --exclude-tags srx345 --exclude-tags eol

Examples

upgrade (package update)

% junos-ops upgrade rt1.example.jp
# rt1.example.jp
remote: jinstall-ppc-18.4R3-S10-signed.tgz is not found.
copy: system storage cleanup successful
rt1.example.jp: cleaning filesystem ...
rt1.example.jp: b'jinstall-ppc-18.4R3-S10-signed.tgz': 380102074 / 380102074 (100%)
rt1.example.jp: checksum check passed.
install: clear reboot schedule successful
install: rescue config save successful
rt1.example.jp: software validate package-result: 0

version (version check)

% junos-ops version rt1.example.jp
# rt1.example.jp
  - hostname: rt1
  - model: MX5-T
  - running version: 18.4R3-S7.2
  - planning version: 18.4R3-S10
    - running='18.4R3-S7.2' < planning='18.4R3-S10'
  - pending version: 18.4R3-S10
    - running='18.4R3-S7.2' < pending='18.4R3-S10' : Please plan to reboot.
  - reboot requested by exadmin at Sat Dec  4 05:00:00 2021

check (pre-flight verification)

Unified pre-flight checks across NETCONF reachability and firmware checksums. Exit code is non-zero if any check fails. Default (no flag) runs --connect only.

--local is inventory-mode and ignores hostnames — it iterates every <model>.file / <model>.hash pair in config.ini and verifies the files on the staging server. No NETCONF required:

% junos-ops check --local
lpath: /opt/firmware
model            file                                                        checksum
---------------  ----------------------------------------------------------  ----------
ex2300-24t       junos-arm-32-23.4R2-S7.4.tgz                                ok
ex3400-24t       junos-arm-32-23.4R2-S7.4.tgz                                ok(cached)
ex4300-32f       jinstall-ex-4300-21.4R3-S12.2-signed.tgz                    ok
mx5-t            jinstall-ppc-21.2R3-S8.5-signed.tgz                         missing

  mx5-t: - local package: /opt/firmware/jinstall-ppc-21.2R3-S8.5-signed.tgz is not found.

Use --model M to restrict the inventory to a single model. For multi-model selection, attach <model>.tags = ... to the relevant rows in config.ini and use --tags (and optionally --exclude-tags) — the same AND/OR grammar as host-side --tags applies, but selectors are matched against the model name and the model's <model>.tags set, not against host tags:

[DEFAULT]
ex2300-24t.file = junos-arm-32-23.4R2-S7.4.tgz
ex2300-24t.hash = ...
ex2300-24t.tags = main, edge       # optional model tags
mx240.file       = ...
mx240.tags       = backbone
# Single model — matches by name, no <model>.tags needed
% junos-ops check --local --tags ex2300-24t

# "main"-tagged models — uses <model>.tags
% junos-ops check --local --tags main

# Multi-selection: model name + tag groups OR together
% junos-ops check --local --tags srx345 --tags backbone

# Drop a model from the result
% junos-ops check --local --tags main --exclude-tags ex3400-24t

For --local-only runs, host-side --tags (the per-host tag selector) is not applied — --local is host-independent, so --tags reinterprets as the model selector described above. Mixing --local with --connect / --remote keeps the host selector active for the per-host part.

Note on --all (or --local --connect/--remote): a single --tags value filters both tables at once — the inventory table by <model>.tags (and model name) and the per-host table by host tags. The two tag namespaces are independent, so keep their names aligned (e.g. a main model tag and a main host tag) if you want --all --tags main to scope both consistently.

--connect / --remote (and --all) are per-host and use the specified hostnames (or every host in config.ini, optionally filtered by --tags). --remote doubles as a "did the SCP copy fully land" check between copy and install:

% junos-ops check --connect --remote rt1.example.jp rt2.example.jp
hostname         connect  remote      model     file
---------------  -------  ----------  --------  -----------------------------------
rt1.example.jp   ok       ok          MX5-T     jinstall-ppc-18.4R3-S10-signed.tgz
rt2.example.jp   ok       missing     MX5-T     jinstall-ppc-18.4R3-S10-signed.tgz

  rt2.example.jp: remote: - remote package: jinstall-ppc-18.4R3-S10-signed.tgz is not found.

When --connect / --remote need to resolve a model and it was not supplied via --model, they fall back to dev.facts["model"] from the live device, or to an optional model = MX5-T key added to the host section in config.ini.

--all runs both: the inventory table is printed first, then the per-host table.

rsi (parallel RSI/SCF collection)

% junos-ops rsi --workers 5 rt1.example.jp rt2.example.jp
# rt1.example.jp
  rt1.example.jp.SCF done
  rt1.example.jp.RSI done
# rt2.example.jp
  rt2.example.jp.SCF done
  rt2.example.jp.RSI done

reboot (scheduled reboot)

% junos-ops reboot --at 2506130500 rt1.example.jp
# rt1.example.jp
	Shutdown at Fri Jun 13 05:00:00 2025. [pid 97978]

config (push set command file)

Push a set-format command file to multiple devices. Uses a safe commit flow: commit check, commit confirmed, then confirm.

% cat add-user.set
set system login user viewer class read-only
set system login user viewer authentication ssh-ed25519 "ssh-ed25519 AAAA..."

% junos-ops config -f add-user.set --dry-run rt1.example.jp rt2.example.jp
# rt1.example.jp
[edit system login]
+    user viewer {
+        class read-only;
+        authentication {
+            ssh-ed25519 "ssh-ed25519 AAAA...";
+        }
+    }
	dry-run: rollback (no commit)
# rt2.example.jp
	...

% junos-ops config -f add-user.set rt1.example.jp rt2.example.jp
# rt1.example.jp
	...
	commit check passed
	commit confirmed 1 applied
	health check: uptime (NETCONF RPC)
	health check passed (uptime: 2026-04-16 13:20:31 JST)
	commit confirmed, changes are now permanent
# rt2.example.jp
	...

Use --confirm N to change the commit confirmed timeout (default: 1 minute). Use --no-health-check to skip the post-commit health check.

Set files can include # comments and blank lines — they are automatically stripped before sending to the device.

Jinja2 Templates

Use .j2 files to generate per-host configurations from a single template. Variables come from var_* keys in config.ini and device facts.

junos-ops config -f ntp.set.j2 --dry-run rt1.example.jp sw1.example.jp
junos-ops config -f ntp.set.j2 rt1.example.jp sw1.example.jp

See docs/template.md for details, usage patterns (conditionals, loops), and config.ini examples.

show (run CLI command)

Run an arbitrary CLI command across multiple devices in parallel. Use --retry N to automatically retry on RpcTimeoutError (useful for large-scale parallel execution).

% junos-ops show "show bgp summary" --config accounts.ini gw1.example.jp gw2.example.jp
# gw1.example.jp
Groups: 4 Peers: 6 Down peers: 0
...
# gw2.example.jp
Groups: 3 Peers: 4 Down peers: 0
...

Use -f to run multiple commands from a file within a single NETCONF session per device:

% cat commands.txt
# security policy check
show security policies hit-count
show security flow session summary

% junos-ops show -f commands.txt --config accounts.ini fw1.example.jp
# fw1.example.jp
## show security policies hit-count
...

## show security flow session summary
...

Use --retry N to retry commands that fail with RpcTimeoutError (with incremental backoff: 5s, 10s, 15s, ...):

% junos-ops show "show system alarms" --retry 2 --workers 10 --config accounts.ini

Structured output (--format)

Use -F / --format {text,json,xml} to change the output format. text is the default (legacy behaviour); json is handy for programmatic consumers and AI assistants; xml returns the pretty-printed RPC reply.

% junos-ops show "show interfaces terse" --format json gw1.example.jp
# gw1.example.jp
## show interfaces terse
{
  "interface-information": {
    "physical-interface": [ ... ]
  }
}

Caveat — pipe stages with json / xml. Over NETCONF, pipe modifiers like | match, | last, and | count are silently dropped when the device is asked to emit json or xml (see Juniper/junos-mcp-server#4 / #12). They are honoured for --format text. If you need to filter structured output, either stay on text and pipe through shell tools (e.g. jc, grep, jq after a separate parse step) or call the equivalent RPC directly.

No subcommand (show device facts)

% junos-ops gw1.example.jp
# gw1.example.jp
{'2RE': True,
 'hostname': 'gw1',
 'model': 'MX240',
 'version': '18.4R3-S7.2',
 ...}

Upgrading low-flash devices (--unlink)

On low-flash devices like EX2300/EX3400 (/dev/gpt/junos = 1.3GB), major upgrades such as 22.4 → 23.4 may fail at the validation step with ERROR: insufficient space. This is because PyEZ's SW.install() does not expose the unlink option of request system software add — its default path never asks pkgadd to unlink the source tgz, so the original package occupies space throughout extraction.

Pass --unlink to invoke request system software add <package> unlink directly via the CLI, so pkgadd unlinks the tgz during installation and frees space as it extracts.

# For low-flash devices
junos-ops upgrade --unlink ex3400-host.example.jp

# Same flag is available on the install-only subcommand
junos-ops install --unlink ex3400-host.example.jp

Supported Models

Any Juniper model can be supported by defining the model name and package file in the configuration file. Models included in the example configuration:

Series Example Models
EX EX2300-24T, EX3400-24T, EX4300-32F
MX MX5-T, MX240
QFX QFX5110-48S-4C
SRX SRX300, SRX345, SRX1500, SRX4600

License

Apache License 2.0

Copyright 2022-2025 AIKAWA Shigechika

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

junos_ops-0.25.1.tar.gz (114.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

junos_ops-0.25.1-py3-none-any.whl (67.0 kB view details)

Uploaded Python 3

File details

Details for the file junos_ops-0.25.1.tar.gz.

File metadata

  • Download URL: junos_ops-0.25.1.tar.gz
  • Upload date:
  • Size: 114.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for junos_ops-0.25.1.tar.gz
Algorithm Hash digest
SHA256 270a27fc2dc280351be860fc9068581509acfdccf6da9c88c7f4b5a7a5ce5843
MD5 fd88b047af161d8feea2bb6e7e7106e8
BLAKE2b-256 82e2b7b642966c036df662b6b690aa2c83298a4f939aa34aaaadb78e9a016efd

See more details on using hashes here.

Provenance

The following attestation bundles were made for junos_ops-0.25.1.tar.gz:

Publisher: release.yml on shigechika/junos-ops

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file junos_ops-0.25.1-py3-none-any.whl.

File metadata

  • Download URL: junos_ops-0.25.1-py3-none-any.whl
  • Upload date:
  • Size: 67.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for junos_ops-0.25.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d1b577a0fa8cc39bcecb6b549efcfac9b4282a1037d8b896fed9ce101ae233a8
MD5 0c77dffcd95def2869dc4a6dc5d8851e
BLAKE2b-256 2397a629c92a795b802cdf8ef1f2f05b80e3119e80e44f3cffb1ec4eced77eff

See more details on using hashes here.

Provenance

The following attestation bundles were made for junos_ops-0.25.1-py3-none-any.whl:

Publisher: release.yml on shigechika/junos-ops

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page