mcpField
N
netbox-custom-scripts

netbox-custom-scripts

github.com/netboxlabs開発2151 回インストール2 週間前に更新
リポジトリ

netbox-custom-scripts について

netbox-custom-scripts は、NetBox 内で動作する Python スクリプトの作成とデバッグを支援するスキルです。変数、ORM の変更、検証、バックグラウンドジョブをバージョン別に案内します。

主な機能

  1. 01スクリプトクラスとフォーム変数の説明
  2. 02ORM 検証と変更ログの解説
  3. 03トランザクション、中断、ジョブ実行の説明
  4. 04バージョン固有の API と ORM 変更の解説
  5. 05実装とデバッグのガイダンス

活用シーン

  1. 01インベントリーを変更する NetBox スクリプトの作成
  2. 02スクリプト変数や実行エラーの調査
  3. 03モデル変更を保存する前のデータ検証
  4. 04NetBox のバージョン変更に合わせたスクリプト調整

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/netboxlabs/skills --skill netbox-custom-scripts

インストール後、Claude Code で/netbox-custom-scriptsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
execution-model.md
orm-patterns.md
script-variables.md

詳細

NetBox カスタムスクリプト

NetBox カスタムスクリプトについての知識は古くなっている可能性があります。 Script クラスの API、変数の型、ジョブフレームワークは、NetBox のリリースごとに変更されます。事前学習済みの知識より、情報を取得して確認することを優先してください。

NetBox 4.7 以降:コアのカスタムスクリプトは非推奨になりました。現時点で対応は不要です。 組み込みの実装は、4.7 および 4.8 のリリースサイクルを通じて引き続き利用でき、サポートされます。NetBox 5.0 で削除される予定です。後継は、オープンソースの netbox-scripts プラグインです(スクリプトをプロジェクト単位で整理し、スクリプト間で Python リソースを共有し、スクリプトごとにバージョン管理できます)。移行は大部分が自動化されることを想定しており、スクリプトを書き直す必要はありません。既存のスクリプトはそのまま動作します。2026 年 9 月時点で、このプラグインはアルファ版(v0.0.1、NetBox 4.7 のみ対応)であり、本番環境での使用は推奨されません。4.5〜4.7 では、このスキルに従ってコアスクリプトを書き続けてください。バージョンに関する注記を参照してください。

情報の取得元

情報源URL / 方法用途
カスタムスクリプトのドキュメントhttps://netboxlabs.com/docs/netbox/customization/custom-scripts/Script クラス、変数、スケジュール設定
NetBox リポジトリhttps://github.com/netbox-community/netboxスクリプトフレームワークのソースコード
netbox-scripts プラグイン (4.7 以降、アルファ版)https://github.com/netbox-community/netbox-scriptsコアスクリプトの後継、移行ワークフロー
NetBox MCP サーバー設定されている場合 — スクリプト実行の前後でオブジェクトの状態を確認スクリプト出力のテスト

最初に:環境を確認する

カスタムスクリプトは NetBox 内で実行されます。NetBox インスタンスが稼働していることと、スクリプトのエンドポイントにアクセスできることを確認してください。

curl -s -H "Authorization: Bearer $NETBOX_TOKEN" "$NETBOX_URL/api/extras/scripts/" | python -m json.tool

インストール済みスクリプトの一覧が表示されます。スクリプトは SCRIPTS_ROOT(デフォルト:/opt/netbox/netbox/scripts/)から読み込まれます。


NetBox 内で実行されるカスタムスクリプトを作成またはデバッグする場合は、このスキルを使用してください。プラグイン開発(新しいモデル、ビュー、API)については、netbox-plugin-developmentを参照してください。

クイックリファレンス

最小限のスクリプト
from extras.scripts import Script, StringVar, ObjectVar
from dcim.models import Site

class HelloWorld(Script):
    class Meta:
        name = "Hello World"
        description = "A minimal example script"
        commit_default = False

    site = ObjectVar(model=Site)

    def run(self, data, commit):
        self.log_success(f"Selected site: {data['site']}", data['site'])
        return "Done"
ログメソッド
メソッドレベル副作用
self.log_debug(msg, obj)DEBUG—
self.log_info(msg, obj)INFO—
self.log_success(msg, obj)SUCCESS—
self.log_warning(msg, obj)WARNING—
self.log_failure(msg, obj)FAILUREself.failed = True を設定

msg と obj はどちらも省略可能です。メッセージでは Markdown を使用できます。obj が get_absolute_url() を持つ場合、UI でクリック可能なリンクになります。

よく使うインポート
from extras.scripts import Script, AbortScript
from extras.scripts import (
    StringVar, TextVar, IntegerVar, BooleanVar, ChoiceVar,
    MultiChoiceVar, ObjectVar, MultiObjectVar, FileVar,
    IPAddressVar, IPAddressWithMaskVar, IPNetworkVar,
    DateVar, DateTimeVar, DecimalVar,
)
from dcim.models import Device, Site, Interface, Rack, Region
from ipam.models import IPAddress, Prefix, VLAN, VRF
from tenancy.models import Tenant
from circuits.models import Circuit

スクリプトの構成

メタ属性
属性デフォルト用途
nameクラス名UI に表示する名前
description''UI に表示する説明
commit_defaultTrueコミットチェックボックスのデフォルト状態
scheduling_enabledTrueスケジュール実行/定期実行を許可
notifications_default (4.6 以降)'always'ジョブの初期通知ポリシー:always、on_failure、または never。イベントルールまたは runscript から実行する場合にも使用されます
job_timeoutRQ_DEFAULT_TIMEOUT実行時間の上限(秒)
field_order宣言順フィールド名のタプル
fieldsetsNoneフィールドのグループ化レイアウト(field_order を上書き)
フィールドセット

UI で関連するフィールドをグループ化します。

class Meta:
    fieldsets = (
        ('Source', ('region', 'site')),
        ('Configuration', ('vlan_id', 'description')),
    )
モジュールレベルでの順序指定

1 つのファイルに複数のスクリプトがある場合の表示順を制御します。

script_order = (ScriptA, ScriptB, ScriptC)

フォーム変数

すべての変数が次の項目に対応しています:label、description、default、required(デフォルトは True)、widget。

変数主なオプション備考
StringVarmin_length、max_length、regex1 行テキスト
TextVar—複数行テキストエリア
IntegerVarmin_value、max_value
BooleanVar—内部では常に任意項目です
ChoiceVarchoices((value, label) のリスト)空の選択肢が自動的に追加されます
MultiChoiceVarchoices複数選択
ObjectVarmodel、query_params、null_option、selector、quick_addAPI 連携の動的なドロップダウンです。selector(4.5 以降)は高度なオブジェクト選択画面を表示し、quick_add(4.6.2 以降)はインラインの「新規作成」ボタンを追加します
MultiObjectVarObjectVar と同じ複数のオブジェクト
FileVar—ファイルのアップロード(実行中のみ利用可能)
IPAddressVar—マスクなしの IPv4/IPv6
IPAddressWithMaskVar—プレフィックス付き IP(例:192.168.1.1/24)
IPNetworkVarmin_prefix_length、max_prefix_lengthネットワークプレフィックス
DateVar / DateTimeVar—日付/時刻ピッカー
DecimalVarmin_value、max_value、max_digits、decimal_places

詳しくは references/script-variables.md を参照してください。

ObjectVar による動的なフィルタリング

query_params で $ プレフィックスを使うと、他のフォームフィールドを参照できます。

region = ObjectVar(model=Region)
site = ObjectVar(model=Site, query_params={'region_id': '$region'})
rack = ObjectVar(model=Rack, query_params={'site_id': '$site'})

UI では、親の選択内容に応じて各ドロップダウンが動的にフィルタリングされます。

ORM アクセスと変更ログ

スクリプトからは Django ORM に完全にアクセスできます。次の 3 つの重要なルールがあります。

1. save() の前に必ず full_clean() を呼び出す
device = Device(name='new-device', site=site, role=role, device_type=dtype)
device.full_clean()   # Validates model constraints — skipping risks data corruption
device.save()
2. 既存のオブジェクトを変更する前に snapshot() を呼び出す
device = Device.objects.get(name='existing')
device.snapshot()     # Required for change log to show a diff
device.status = 'active'
device.full_clean()
device.save()
3. コンテキストには _changelog_message を使用する(任意)
device._changelog_message = 'Bulk status update via maintenance script'
device.save()
スクリプトに影響する NetBox 4.7 の ORM の変更点
  • カスタムフィールドのデータ:すべてのバージョンで、スクリプト内の obj.custom_field_data['x'] は引き続き保存時の 生の値 です。変更されたのは 4.7 の REST/GraphQL 表現のみです(選択フィールドは {"value": ..., "label": ...} を返します)。ORM から辞書が返されることは想定しないでください。
  • CustomField.objects.get_for_model() と obj.custom_fields は、4.7 ではリストを返します(有効なフィールドのみ)。4.5/4.6 ではクエリーセットです。これらに .filter()/.exclude() を連結しないでください。代わりにリスト内包表記を使用してください。
  • 階層モデルは 4.7 で ltree を使用します(Region、SiteGroup、Location、DeviceRole、Platform、TenantGroup、…)。get_ancestors()、get_descendants()、get_children() は引き続き使用できます。level は Python プロパティのみとなり(.filter(level=…)/.order_by('level') は使用できません)、get_root()、get_family()、is_leaf_node()、move_to()、insert_at() は削除されました。
  • 4.7 ではグローバル検索インデックスの更新がバックグラウンドジョブに延期されます。スクリプトで作成したばかりのオブジェクトは、短時間、グローバル検索に表示されない場合があります(ORM の検索には影響しません)。

クエリーの最適化、一括処理のパターン、および上記のバージョン条件付きの例については、references/orm-patterns.md を参照してください。

トランザクション処理

すべてのスクリプト実行は transaction.atomic() でラップされます。 つまり、次のようになります。

  • commit=True:スクリプトがエラーなく完了した場合、変更は保持されます
  • commit=False:run() の完了後、すべての DB 変更がロールバックされます(ドライランモード)
  • 例外が発生した場合:commit の設定にかかわらず、すべての変更がロールバックされます
  • スクリプトの一部だけをコミットすることはできません — すべてコミットするか、すべてロールバックするかのどちらかです
正常な中断
from utilities.exceptions import AbortScript

if critical_error:
    raise AbortScript("Clear error message")

AbortScript はメッセージを失敗として記録し、すべての変更をロールバックします。出力にスタックトレースは表示されません。

log_failure は中断しません

self.log_failure() を呼び出すと self.failed = True が設定されます(UI に警告が表示されます)が、実行は停止しません。実際に処理を停止するには AbortScript を使用してください。

実行モデル

スクリプトは Django-RQ を介してバックグラウンドジョブとして実行されます。

  • UI/API からの送信 → ジョブが Redis にキューイングされる → RQ ワーカーが実行
  • CLI:python manage.py runscript --commit --user admin module.ClassName
  • スケジュール設定:将来の実行には schedule_at、繰り返し実行には interval を設定します
  • タイムアウト:Meta.job_timeout またはグローバルな RQ_DEFAULT_TIMEOUT で制御します

NetBox 4.7 以降 — REST による実行: POST /api/extras/scripts/<id>/ には、書き込みが有効なトークンが必要です。読み取り専用トークンでは、スクリプトが解決される前に HTTP 403 が返されます。4.7.1 以降、data ペイロードはスクリプトで宣言された変数に照らして検証され(不足/無効な場合は HTTP 400、未宣言のキーは破棄)、ObjectVar の ID は run() の前にモデルインスタンスへ解決されます。ID を渡してください。例:{"data": {"site": 1}}。FileVar を含むスクリプトは multipart/form-data を介して実行する必要があります。完了したジョブには execution_time が記録されます(4.7)。

NetBox 4.6 以降 — 通知: 各実行には notifications 実行パラメーター(always/on_failure/never。UI フォームフィールド、REST ボディキー。デフォルト値は Meta.notifications_default)があります。スケジュール実行の完了を検知するために UI 通知に頼らず、ジョブをポーリングしてください。NetBox 4.6.2 では、スケジュール済みバックグラウンドジョブの重複も防止されます(キューに登録済みの繰り返しジョブを再送信しても、重複して追加されなくなりました)。

ジョブのライフサイクルについては、references/execution-model.md を参照してください。

ジョブの状態

PENDING → RUNNING → COMPLETED | ERRORED | FAILED

または SCHEDULED → PENDING → ...

検証レポート(テストメソッド)

test_* という名前のメソッドは自動検出され、検証チェックとして実行されます。

class CablingAudit(Script):
    class Meta:
        name = "Cabling Audit"

    def test_console_connections(self):
        for device in Device.objects.filter(status='active'):
            ports = ConsolePort.objects.filter(device=device)
            for port in ports:
                if port.connected_endpoints:
                    self.log_success(None, port)  # Count success without message
                else:
                    self.log_failure(f"No console connection: {port}", device)

run() がオーバーライドされていない場合、NetBox は pre_run() → すべての test_* メソッド → post_run() の順に実行します。

NetBox 4.0 以降:レポートはスクリプトに統合されました。従来のレポートログシグネチャ (obj, message) も引き続き動作しますが、非推奨です。(message, obj) を使用してください。

アンチパターン

間違い結果修正方法
full_clean() を省略するデータ整合性違反保存前に必ず検証する
snapshot() を省略する変更ログに差分が表示されない既存オブジェクトを変更する前に呼び出す
log_failure で停止すると想定するスクリプトの実行が続くAbortScript を使って停止する
実行時間の長いスクリプトタイムアウトで強制終了されるMeta.job_timeout を設定する
from netbox.dcim.models からインポートするImportErrorfrom dcim.models import ... を使う
FileVar が保持されると想定するファイルは実行中のみ利用可能run() でファイルを処理/コピーする
CLI で self.request.user に依存するNetBoxFakeRequest が取得される適切に処理する
モジュール名が競合するインポートの衝突インストール済みパッケージと同じ名前のスクリプトは避ける
読み取り専用トークンで REST 経由の実行を試みる (4.7)HTTP 403書き込みが有効なトークンを使う
obj.custom_fields に対して .filter() を使う (4.7)AttributeError — リストですリスト内包表記を使う
Region.objects.filter(level=0)/get_root() を使う (4.7)FieldError/AttributeError — ltreeparent__isnull=True;get_ancestors()
作成直後のオブジェクトがグローバル検索に表示されると想定する (4.7)インデックスはバックグラウンドジョブで更新される検索インデックスではなく ORM にクエリする

スクリプトファイルの管理

  • スクリプトは、SCRIPTS_ROOT(デフォルト:$INSTALL/netbox/scripts/)に置かれた Python ファイルです
  • UI(Admin > Custom Scripts)からアップロードするか、ファイルを直接配置します
  • 各ファイルは ScriptModule になり、クラスは自動的に検出されます
  • ファイルからクラスを削除すると、ジョブ履歴がある場合はその DB レコードがソフト削除されます(is_executable=False)
  • ストレージバックエンドは Django の STORAGES で設定できます(S3 に対応)
  • スクリプトはリモートの DataSource(git/S3)から同期することもできます。NetBox 4.6.2+ では、リモートソースのスクリプトは同期時に検証されるため、不正なスクリプトは初回実行時ではなく同期時に検出されます
  • REST 経由でアップロードするには、POST /api/extras/scripts/upload/(multipart/form-data、[email protected])を使用します。4.6.5+ では、PUT/PATCH を /api/extras/scripts/upload/<module>.py/ に送信して、既存のモジュールをそのまま置き換えられます

バージョンに関する注意事項

NetBox 4.7(2026-09-02)
  • netbox-scripts プラグインを優先し、コアのカスタムスクリプトは非推奨になりました(4.7 および 4.8 までサポートされ、5.0 で削除されます)。既存のスクリプトは引き続き動作し、移行は自動化される予定です。2026 年 9 月時点で、プラグインはアルファ版です。
  • REST での実行には書き込み可能なトークンが必要です(それ以外の場合は 403)。4.7.1:REST 入力が宣言済み変数に対して検証され、オブジェクト ID はインスタンスに解決されます。
  • Job.execution_time(読み取り専用の所要時間)がジョブの REST 表現に追加されました。
  • 選択/複数選択のカスタムフィールド値は、REST/GraphQL では {value, label} オブジェクトになります。ORM の obj.custom_field_data は変更されず(生の値のまま)です。
  • CustomField.objects.get_for_model() / obj.custom_fields は、クエリセットではなく有効なフィールドのリストを返します。デフォルト値を指定したカスタムフィールドの作成と削除は、BULK_UPDATE_CHUNK_SIZE を超える場合、バックグラウンドジョブに延期されます。このようなフィールドは status が provisioning/deleting となり、処理が完了するまで get_for_model() から除外されます。
  • 階層モデルは MPTT から PostgreSQL の ltree に移行しました。level はフィルターや並べ替えに使用できなくなり、get_root()、get_family()、is_leaf_node()、move_to()、insert_at() は削除されました。
  • グローバル検索インデックスの更新はバックグラウンドジョブに延期されます(作成/更新後に一時的な遅延が発生します)。
  • アップグレードの前提条件:PostgreSQL 15 以降、Redis 6.0 以降、ltree 拡張機能。4.7.3 以降を推奨します(4.7.0/4.7.1 では、バックグラウンドの一括リクエストで作成された API トークンがジョブ結果に平文で記録されました。4.7.3 では、ブランチセーフなバックグラウンド書き込みと config-context の omit 最適化が追加されました)。
NetBox 4.6(2026-05-05)
  • notifications 実行パラメーター(always/on_failure/never)と Meta.notifications_default。4.6.2 では、スケジュール済みのバックグラウンドジョブが重複しないようになりました。
  • ObjectVar(quick_add=True)(4.6.2)、リモートソースのスクリプトを同期時に検証(4.6.2)、アップロード済みスクリプトモジュールを置き換える REST PUT/PATCH(4.6.5)。

コメント