Juniperデバイスのモデルを自動検出し、JUNOSパッケージを自動更新するツールです。
- デバイスモデルの自動検出とパッケージの自動マッピング
- SCP転送+チェックサム検証による安全なパッケージコピー
- インストール前のパッケージ検証(validate)
- ロールバック対応(MX/EX/SRXモデル別処理)
- スケジュールリブート
- RSI(request support information)/ SCF(show configuration | display set)の並列収集
- ドライランモード(
--dry-run)で事前確認 - ThreadPoolExecutor による並列実行
- config サブコマンドの並列実行対応(
--workersで並列数指定) - Jinja2 テンプレートによるホスト別設定生成(詳細)
- 設定ファイル(INI形式)によるホスト・パッケージ管理
brew install shigechika/tap/junos-opspip install junos-ops最新版に更新する場合:
pip install junos-ops --upgradegit clone https://github.com/shigechika/junos-ops.git
cd junos-ops
python3 -m venv .venv
. .venv/bin/activate
pip install -e ".[test]"- junos-eznc (PyEZ) — Juniper NETCONF自動化ライブラリ
- looseversion — バージョン比較
pip install junos-ops[completion]
eval "$(register-python-argcomplete junos-ops)"eval の行を ~/.bashrc や ~/.zshrc に追記すると常時有効になります。
OS別手順
-
Ubuntu/Debian
sudo apt install python3-pip
-
CentOS/RedHat
sudo dnf install python3-pip
-
macOS
brew install python3
INI形式の設定ファイルで、接続情報とモデル別パッケージを定義します。
設定ファイルは以下の順序で探索されます(-c / --config で明示指定も可能):
- カレントディレクトリの
./config.ini ~/.config/junos-ops/config.ini(XDG_CONFIG_HOME)
logging.ini を配置すると、ログ出力をカスタマイズできます(例: paramiko/ncclient の冗長なログを抑制)。config.ini と同じ順序で探索されます:
- カレントディレクトリの
./logging.ini ~/.config/junos-ops/logging.ini(XDG_CONFIG_HOME)
どちらも見つからない場合は、デフォルトのログ設定(INFO レベル、stdout 出力)が使用されます。
全ホスト共通の接続設定とモデル→パッケージマッピングを記述します。
[DEFAULT]
id = exadmin # SSHユーザ名
pw = password # SSHパスワード
sshkey = id_ed25519 # SSH秘密鍵ファイル
port = 830 # NETCONFポート
hashalgo = md5 # チェックサムアルゴリズム
rpath = /var/tmp # リモートパス
# lpath = ~/firmware # ローカルのファームウェア置き場(~ 展開対応、デフォルト: カレントディレクトリ)
# huge_tree = true # 大きなXMLレスポンスを許可
# RSI_DIR = ./rsi/ # RSI/SCFファイルの出力先
# DISPLAY_STYLE = display set # SCF出力形式(デフォルト: display set)
# DISPLAY_STYLE = # 空にすると show configuration のみ(stanza形式)
# モデル名.file = パッケージファイル名
# モデル名.hash = チェックサム値
EX2300-24T.file = junos-arm-32-18.4R3-S10.tgz
EX2300-24T.hash = e233b31a0b9233bc4c56e89954839a8aモデル名はデバイスから自動取得されるmodelフィールドと一致させます。
各セクション名がホスト名になります。DEFAULTの値をホスト単位でオーバーライドできます。
[rt1.example.jp] # セクション名がそのまま接続先ホスト名
tags = tokyo, core # タグベースのホストフィルタリング(--tags)
[rt2.example.jp]
host = 192.0.2.1 # IPアドレスで接続先を指定
tags = osaka, core
[sw1.example.jp]
id = sw1 # 接続ユーザを変更
sshkey = sw1_rsa # SSH鍵を変更
tags = tokyo, access
[sw2.example.jp]
port = 10830 # ポートを変更
[sw3.example.jp]
EX4300-32F.file = jinstall-ex-4300-20.4R3.8-signed.tgz # このホストだけ別バージョン
EX4300-32F.hash = 353a0dbd8ff6a088a593ec246f8de4f4junos-ops <subcommand> [options] [hostname ...]
| サブコマンド | 説明 |
|---|---|
upgrade |
コピー+インストールを一括実行 |
copy |
ローカルからリモートへパッケージをコピー |
install |
コピー済みパッケージをインストール |
rollback |
前バージョンにロールバック |
version |
running/planning/pendingバージョンとリブート予定を表示 |
reboot --at YYMMDDHHMM |
指定日時にリブートをスケジュール |
ls [-l] |
リモートパスのファイル一覧 |
config -f FILE [--confirm N] [--no-confirm] [--timeout N] |
set コマンドファイルを適用 |
rsi |
RSI/SCF を並列収集 |
| (なし) | デバイスファクト(device facts)を表示 |
| オプション | 説明 |
|---|---|
hostname |
対象ホスト名(省略時は設定ファイル内の全ホスト) |
-c, --config CONFIG |
設定ファイル指定(デフォルト: config.ini → ~/.config/junos-ops/config.ini) |
-n, --dry-run |
テスト実行(接続とメッセージ出力のみ、実行しない) |
-d, --debug |
デバッグ出力 |
--force |
条件を無視して強制実行 |
--tags TAG,... |
タグでホストをフィルタ(カンマ区切り、AND マッチ) |
--workers N |
並列実行数(デフォルト: upgrade系=1, rsi=20) |
--version |
プログラムバージョン表示 |
すべてのサブコマンドは共通の実行パイプラインを通ります。設定ファイルを読み込み、対象ホストを決定し(--tags で絞り込み可能)、ThreadPoolExecutor でホストごとにワーカースレッドへ振り分けます。--workers N で並列数を制御でき、upgrade 系はデフォルト 1(安全な逐次実行)、RSI 収集はデフォルト 20(I/O バウンドのため並列化が有効)です。各ワーカーは独立した NETCONF セッションを確立するため、ホスト間で状態を共有しません。
flowchart TD
A[junos-ops CLI] --> B[config.ini 読み込み]
B --> C[対象ホスト決定]
C --> D{サブコマンド}
D --> E[upgrade / copy / install]
D --> F[version / rollback / reboot]
D --> G[config / show / ls]
D --> H[rsi]
D --> I["(なし)→ facts"]
E & F & G & H & I --> J["ThreadPoolExecutor<br/>--workers N"]
J --> K["NETCONF / SCP<br/>ホストごとに実行"]
K --> L[結果出力]
ファームウェア更新はリスクを最小化する4ステップで構成されています。まず dry-run で接続性・パッケージの存在・チェックサムを変更なしで検証します。次に upgrade でコピーとインストールを実行します。version でインストール後の pending バージョンが想定通りか確認し、問題がなければリブートをスケジュールします。リブートを別ステップにしているのは、メンテナンスウィンドウを選択できるようにするためです。リブート前であればいつでも rollback で元のファームウェアに戻せます。
flowchart TD
A["1. 事前確認<br/>junos-ops upgrade -n"] --> B["2. アップグレード<br/>junos-ops upgrade"]
B --> C["3. バージョン確認<br/>junos-ops version"]
C --> D["4. リブート<br/>junos-ops reboot --at"]
D -.->|"問題発生時"| E["ロールバック<br/>junos-ops rollback"]
1. dry-run で事前確認
junos-ops upgrade -n hostname
2. upgrade でコピー+インストール
junos-ops upgrade hostname
3. version でバージョン確認
junos-ops version hostname
4. reboot でリブート日時を指定
junos-ops reboot --at 2506130500 hostname
問題が発生した場合は rollback で前バージョンに戻せます。
upgrade サブコマンドは更新前後に複数の安全チェックを行います。まず実行中バージョンと目標バージョンを比較し、一致していればスキップします。異なる pending バージョンが存在する場合は先にロールバックしてから進行します。コピーフェーズではディスク容量を確保(ストレージ cleanup + EX/QFX ではスナップショット削除)し、safe_copy でチェックサム検証付きの転送を行い破損を検出します。インストール前に既存のリブートスケジュールを解除し、rescue config を復旧基点として保存します。最後に sw.install() がデバイス上でパッケージの整合性を検証してから適用します。
flowchart TD
A[NETCONF 接続] --> B{"実行中バージョン<br/>= 目標?"}
B -->|yes| C([スキップ — 更新不要])
B -->|no| D{"pending バージョン<br/>あり?"}
D -->|no| E[copy]
D -->|yes| F{pending ≥ 目標?}
F -->|yes, --force なし| C
F -->|no / --force| G[pending をロールバック]
G --> E
subgraph copy ["copy()"]
E --> H[ストレージ cleanup]
H --> I["スナップショット削除<br/>(EX/QFX のみ)"]
I --> J["safe_copy(SCP 転送)<br/>+ チェックサム検証"]:::safe
end
J --> K[リブートスケジュール解除]
K --> L[rescue config 保存]:::safe
L --> M["sw.install()<br/>validate + チェックサム検証"]:::install
M --> N([完了 — リブート待ち])
classDef safe fill:#d4edda,stroke:#28a745,color:#000
classDef install fill:#cce5ff,stroke:#007bff,color:#000
reboot はリブートスケジュール設定前に、ファームウェアインストール後に設定変更がなかったかを自動検出します。変更があった場合は rescue config を再保存し、validation 付きで再インストールを行い、新ファームウェアと現在の設定の互換性を確認します。
flowchart TD
A[NETCONF 接続] --> B{"既存リブート<br/>スケジュールあり?"}
B -->|no| D
B -->|yes| C{--force?}
C -->|no| B2([スキップ — 既存スケジュール維持])
C -->|yes| CL[既存スケジュール解除] --> D
D{"pending バージョン<br/>あり?"} -->|no| SCH
D -->|yes| E[最終コミット時刻を取得]
E --> F[rescue config 時刻を取得]
F --> G{"インストール後に<br/>設定変更あり?"}
G -->|no| SCH
G -->|yes| H[rescue config 再保存]:::warned
H --> I["ファームウェア再インストール<br/>(validate + チェックサム検証)"]:::install
I -->|成功| SCH
I -->|失敗| ERR([中止 — リブートしない]):::errstyle
SCH["リブートスケジュール設定<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 サブコマンドは安全なコミットフローを採用しています。commit confirmed(自動ロールバックタイマー) → ヘルスチェック → commit(確定)の順に実行します。ヘルスチェックが失敗した場合、最終 commit を送信せず、タイマー満了時に JUNOS が自動的にロールバックします。
ヘルスチェック(uptime、ping、CLI コマンド)、commit confirmed フロー、--no-confirm、並列実行などの詳細は docs/config.ja.md を参照してください。
1. dry-run で差分を確認
junos-ops config -f commands.set --dry-run hostname
2. 適用
junos-ops config -f commands.set hostname
3. NETCONF ヘルスチェックで適用(ping 不要)
junos-ops config -f commands.set --health-check uptime hostname
--tags で config.ini に定義したタグでホストを絞り込めます。複数タグは AND マッチ(すべてのタグを持つホストのみ)。明示的なホスト名と組み合わせた場合は union(和集合)になります。
# tokyo タグを持つ全ホスト
junos-ops version --tags tokyo
# tokyo AND core の両方のタグを持つホスト
junos-ops version --tags tokyo,core
# タグフィルタと明示ホストの union
junos-ops version --tags core rt3.example.jp
% 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
% 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
% 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
% junos-ops reboot --at 2506130500 rt1.example.jp
# rt1.example.jp
Shutdown at Fri Jun 13 05:00:00 2025. [pid 97978]
set 形式のコマンドファイルを複数デバイスに適用します。commit check → commit confirmed → 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
health check: ping count 3 255.255.255.255 rapid
health check passed (3 packets received)
commit confirmed, changes are now permanent
# rt2.example.jp
...
--confirm N で commit confirmed のタイムアウトを変更できます(デフォルト: 1分)。--no-health-check でコミット後のヘルスチェックをスキップできます。
set ファイルには # コメント行や空行を含めることができます。適用前に自動的に除去されます。
.j2 ファイルを使って、1つのテンプレートからホストごとに異なる設定を生成できます。変数は config.ini の var_* キーとデバイスファクトから取得されます。
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条件分岐やループなど詳しい使い方は docs/template.ja.md を参照してください。
任意の CLI コマンドを複数デバイスに対して並列実行します。--retry N で RpcTimeoutError 発生時に自動リトライできます(大量ホストへの一括実行時に有効)。
% junos-ops show "show bgp summary" -c 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
...
-f でファイルから複数コマンドを読み込み、デバイスごとに1つの NETCONF セッション内で順次実行します。
% cat commands.txt
# セキュリティポリシー確認
show security policies hit-count
show security flow session summary
% junos-ops show -f commands.txt -c accounts.ini fw1.example.jp
# fw1.example.jp
## show security policies hit-count
...
## show security flow session summary
...
--retry N で RpcTimeoutError 時に自動リトライします(バックオフ: 5秒, 10秒, 15秒, ...):
% junos-ops show "show system alarms" --retry 2 --workers 10 -c accounts.ini
注意: JUNOS CLI のパイプフィルタ(
| match、| count等)は使用できません。PyEZ のdev.cli()は NETCONF RPC 経由でコマンドを送信するため、パイプ修飾子は処理されません。出力のフィルタにはシェル側のツール(grep等)を使用してください。
% junos-ops gw1.example.jp
# gw1.example.jp
{'2RE': True,
'hostname': 'gw1',
'model': 'MX240',
'version': '18.4R3-S7.2',
...}
設定ファイルでモデル名とパッケージファイルを定義することで、任意のJuniperモデルに対応できます。設定例に含まれるモデル:
| シリーズ | モデル例 |
|---|---|
| EX | EX2300-24T, EX3400-24T, EX4300-32F |
| MX | MX5-T, MX240 |
| QFX | QFX5110-48S-4C |
| SRX | SRX300, SRX345, SRX1500, SRX4600 |
Copyright 2022-2025 AIKAWA Shigechika