Automated JUNOS package management tool for Juniper Networks devices
Project description
junos-ops
A tool for automatic detection of Juniper device models and automated JUNOS package updates.
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
- Parallel RSI (request support information) / SCF (show configuration | display set) collection
- Dry-run mode (
--dry-run) for pre-flight verification - Parallel execution via ThreadPoolExecutor
- Configuration push with commit confirmed safety (parallel execution supported)
- INI-based host and package management
Table of Contents
Installation
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
- junos-eznc (PyEZ) — Juniper NETCONF automation library
- looseversion — Version comparison
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):
./config.iniin the current directory~/.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:
./logging.iniin the current directory~/.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
# 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
[rt2.example.jp]
host = 192.0.2.1 # Override connection target with IP address
[sw1.example.jp]
id = sw1 # Override SSH username
sshkey = sw1_rsa # Override SSH key
[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 |
Copy and install package |
copy |
Copy package from local to remote |
install |
Install a previously copied package |
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 |
config -f FILE [--confirm N] |
Push a set command file to devices |
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 |
--workers N |
Parallel workers (default: 1 for upgrade, 20 for rsi) |
--version |
Show program version |
Workflow
JUNOS Upgrade Workflow
1. Pre-flight check with dry-run
junos-ops upgrade -n 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.
Config Push Workflow
1. Preview changes with dry-run
junos-ops config -f commands.set -n hostname
2. Apply changes
junos-ops config -f commands.set hostname
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
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 -n 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
commit confirmed, changes are now permanent
# rt2.example.jp
...
Use --confirm N to change the commit confirmed timeout (default: 1 minute).
No subcommand (show device facts)
% junos-ops gw1.example.jp
# gw1.example.jp
{'2RE': True,
'hostname': 'gw1',
'model': 'MX240',
'version': '18.4R3-S7.2',
...}
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
Copyright 2022-2025 AIKAWA Shigechika
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file junos_ops-0.5.1.tar.gz.
File metadata
- Download URL: junos_ops-0.5.1.tar.gz
- Upload date:
- Size: 33.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a24d00c9badc8db0340dd0802913f361990639b6d04b65ec3d379ac34685e411
|
|
| MD5 |
81c957c587a804082806077ec87d4d04
|
|
| BLAKE2b-256 |
9eecd1992e25042895a37ca41f253959f133935f5b6dfc519a93458058801a77
|
Provenance
The following attestation bundles were made for junos_ops-0.5.1.tar.gz:
Publisher:
release.yml on shigechika/junos-ops
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
junos_ops-0.5.1.tar.gz -
Subject digest:
a24d00c9badc8db0340dd0802913f361990639b6d04b65ec3d379ac34685e411 - Sigstore transparency entry: 947941751
- Sigstore integration time:
-
Permalink:
shigechika/junos-ops@4e556401ad53f79f578526d0d28b4341fe436ed4 -
Branch / Tag:
refs/tags/v0.5.1 - Owner: https://github.com/shigechika
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4e556401ad53f79f578526d0d28b4341fe436ed4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file junos_ops-0.5.1-py3-none-any.whl.
File metadata
- Download URL: junos_ops-0.5.1-py3-none-any.whl
- Upload date:
- Size: 24.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
727a830e1a37e8ba323ac7ef20c2894dd0c22996660e9292aa11eaec3abfe19a
|
|
| MD5 |
34504429bf0043631a5f1d879cd4bbaf
|
|
| BLAKE2b-256 |
22e8362e1e4fd935165cd4ca23c1d2df2d285b54615d43ca20aafd305fee3280
|
Provenance
The following attestation bundles were made for junos_ops-0.5.1-py3-none-any.whl:
Publisher:
release.yml on shigechika/junos-ops
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
junos_ops-0.5.1-py3-none-any.whl -
Subject digest:
727a830e1a37e8ba323ac7ef20c2894dd0c22996660e9292aa11eaec3abfe19a - Sigstore transparency entry: 947941807
- Sigstore integration time:
-
Permalink:
shigechika/junos-ops@4e556401ad53f79f578526d0d28b4341fe436ed4 -
Branch / Tag:
refs/tags/v0.5.1 - Owner: https://github.com/shigechika
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4e556401ad53f79f578526d0d28b4341fe436ed4 -
Trigger Event:
push
-
Statement type: