Before committing ANY change:
- Run syntax check:
python -m compileall netbox_proxbox tests - Run linter:
rtk ruff check . - Run tests:
rtk pytest tests/
Follow the same dependency order agents use (see AGENTS.md):
- NetBox plugin layer — Reuse this plugin’s established patterns and NetBox’s plugin APIs (registration, plugin paths,
NetBoxModel/NetBoxModelViewSet, tables and filtersets consistent with other plugin code here). - NetBox core — Prefer
utilities.forms.fields,utilities.forms.widgets,utilities.views, and otherutilities.*/netbox.*primitives before inventing parallel implementations. - Django — Use
django.forms,django.http, ORM, and related stdlib-backed APIs when NetBox does not offer a specific helper.
Third-party packages: Do not introduce new PyPI dependencies for capabilities NetBox or Django already cover. The project already declares requests, websockets, and optional CLI-related packages in pyproject.toml; add new deps only for integration needs that have no NetBox/Django path, not as shortcuts for UI or API patterns the core stack handles.
Example: NetBox may remove or rename widgets (for example legacy Select2 helpers under utilities.forms.widgets). Prefer current NetBox field/widget pairs such as DynamicModelMultipleChoiceField with API-driven multi-select rather than pulling in extra front-end or Python widget libraries. For form layout and field choices in this plugin, see netbox_proxbox/forms/CLAUDE.md.
- Registered CRUD (via
register_model_viewandnetbox.views.generic) inherits NetBoxObjectPermissionRequiredMixin: model permissions plusqueryset.restrict()for object-level rules. - Custom views should use
utilities.views.ConditionalLoginRequiredMixin(respectsLOGIN_REQUIRED) instead of Django’s unconditionallogin_required, andTokenConditionalLoginRequiredMixinwhere REST tokens should authenticate browser-style endpoints. - Operational endpoints (sync actions, schedule job, WebSocket bridge):
ContentTypePermissionRequiredMixinwith permissions defined innetbox_proxbox/views/proxbox_access.py— typicallyaddon coreJobfor queueing sync work,deleteon coreJobfor cancel actions, andviewonFastAPIEndpointfor read-only WebSocket test UI. - Dashboard and JSON helpers: plugin home requires at least one of
viewonProxmoxEndpoint/NetBoxEndpoint/FastAPIEndpointwhen the user is authenticated; endpoint lists use.restrict(request.user, "view"). Proxmox card and keepalive JSON resolve objects through restricted querysets (get_object_or_404(...restrict(...))). Tagged devices and VMs useDevice.objects.restrict/VirtualMachine.objects.restrictbefore listing. - Plugin REST API remains on
NetBoxModelViewSetwith standard NetBox/DRF permission classes.
This repository packages the netbox_proxbox NetBox plugin. The plugin adds endpoint inventory for Proxmox, NetBox, and the companion ProxBox FastAPI backend; UI pages for sync operations and status checks; REST API endpoints for those models; and a small amount of browser-side JavaScript and styling for the plugin pages.
- The plugin supports both traditional host/venv NetBox deployments and Docker-based NetBox deployments (for example
netbox-community/netbox-docker). - Docker-based plugin installation docs are maintained at
docs/installation/3-installing-plugin-docker.md, includingplugin_requirements.txtandconfiguration/plugins.pyusage. - Backend Docker examples map host
8800to container8000(-p 8800:8000) because the publishedproxbox-apiimage serves through nginx on container port8000.
The current plugin config lives in netbox_proxbox/__init__.py. It declares plugin version 0.0.9.post4 and NetBox compatibility 4.5.0 through 4.5.99.
ProxmoxEndpoint,NetBoxEndpoint,FastAPIEndpoint,ProxmoxStorage,VMBackup,VMSnapshot,VMTaskHistory, andProxboxPluginSettingsare the plugin's main persisted models.- NetBox UI routes live in
netbox_proxbox/urls.pyand are implemented primarily innetbox_proxbox/views/. - The plugin also exposes a NetBox plugin API under
netbox_proxbox/api/, using serializers, filtersets, and standardNetBoxModelViewSetclasses. - Sync actions enqueue NetBox background jobs (
ProxboxSyncJob) that call the external ProxBox FastAPI SSE endpoints and record progress/result on the Job row. - Browser updates can flow over SSE streams or the existing WebSocket channel.
- Templates and static assets are conventional Django plugin assets under
netbox_proxbox/templates/andnetbox_proxbox/static/.
- Single FastAPI row: HTTP and WebSocket helpers such as
get_fastapi_request_context()innetbox_proxbox/services/backend_proxy.py,websocket_client, and several dashboard views resolve the backend viaFastAPIEndpoint.objects.first()(or the first row from a restricted queryset). If multiple FastAPI endpoints exist, whichever row sorts first is used; plan automation and operator docs accordingly. - Background Proxbox sync jobs (RQ):
ProxboxSyncJobenqueues on NetBox’sdefaultRQ queue (RQ_QUEUE_DEFAULT) so a stockmanage.py rqworker(no queue arguments) picks them up. NetBox’s default worker only listens tohigh,default, andlow; the extra django-rq queuenetbox_proxbox.syncis still registered for the plugin but is no longer the enqueue target. Older Job rows may still shownetbox_proxbox.syncin Queue; cancel/RQ lookup uses the stored name. Jobs call proxbox-api SSE viarun_sync_streamuntil a terminalcompleteevent. - RQ timeout vs HTTP stream: NetBox’s default
RQ_DEFAULT_TIMEOUT(often 300s viaconfiguration.py) applies to RQ jobs unless overridden. Long syncs were previously killed by RQ whilerequestswas still reading the SSE body. The plugin sets a defaultjob_timeoutofPROXBOX_SYNC_JOB_TIMEOUT(7200s) inProxboxSyncJob.enqueue; pass a largerjob_timeout=toenqueue()if needed. That is separate from the HTTP between-chunk read timeout (3600s) insiderun_sync_stream. - When a job looks “stuck”: pending usually means no RQ worker is running (or it does not listen to
default). running for a long time usually means proxbox-api is still syncing or the stream is slow/buffered; errored withJobTimeoutExceptionmeans RQ’s wall-clock limit was hit—increasejob_timeoutorPROXBOX_SYNC_JOB_TIMEOUT. Inspect the job log and error fields before changing code. - Cancel on Job detail: For Proxbox Sync rows in pending, scheduled, or running state, the plugin adds Cancel job (POST to
proxbox-cancel). It requires delete permission on the core Job model, cancels or stops the linked RQ job when possible, then marks the NetBox job failed with a “Cancelled by user.” message. Stopping a running job is best-effort (RQ stop + long HTTP reads may not abort instantly). - Run now on Job detail: Shown only when the job is in a terminal state (completed, errored, or failed), including after Cancel (failed). It is not shown for pending, scheduled, or running—use Cancel first if a queued run should be abandoned, then Run now on the finished row to queue a new sync with the same parameters.
- Full update (UI vs jobs): The plugin home may still use non-streaming helpers such as
sync_full_update_resourcefor JSON/redirect flows. Scheduled or immediate Proxbox Sync jobs usefull-update/streamon proxbox-api and execute the full stage chain in one stream: devices, storage, virtual machines, virtual disks, backups, and snapshots.
- Start with
netbox_proxbox/CLAUDE.mdfor the package-level map. - Go to
models,views, andapifirst when changing behavior. - Use
forms,filtersets, andtableswhen changing how plugin objects are edited or listed in NetBox. - Use
templatesandstatictogether when adjusting UI behavior, page structure, or browser-side interactions. - Check
migrationsbefore changing any model field or constraint. - For sync streaming changes, see
views/CLAUDE.md(SSE proxy),static/netbox_proxbox/js/CLAUDE.md(browser SSE parsing), andtemplates/netbox_proxbox/CLAUDE.md(stream URL wiring).
netbox_proxbox/CLAUDE.mdnetbox_proxbox/api/CLAUDE.mdnetbox_proxbox/forms/CLAUDE.mdnetbox_proxbox/migrations/CLAUDE.mdnetbox_proxbox/models/CLAUDE.mdnetbox_proxbox/static/CLAUDE.mdnetbox_proxbox/static/netbox_proxbox/CLAUDE.mdnetbox_proxbox/static/netbox_proxbox/js/CLAUDE.mdnetbox_proxbox/static/netbox_proxbox/styles/CLAUDE.mdnetbox_proxbox/tables/CLAUDE.mdnetbox_proxbox/templates/CLAUDE.mdnetbox_proxbox/templates/netbox_proxbox/CLAUDE.mdnetbox_proxbox/templates/netbox_proxbox/base/CLAUDE.mdnetbox_proxbox/templates/netbox_proxbox/fastapi/CLAUDE.mdnetbox_proxbox/templates/netbox_proxbox/home/CLAUDE.mdnetbox_proxbox/templates/netbox_proxbox/partials/CLAUDE.mdnetbox_proxbox/templates/netbox_proxbox/proxmox/CLAUDE.mdnetbox_proxbox/templates/netbox_proxbox/table/CLAUDE.mdnetbox_proxbox/templates/netbox_proxbox/test/CLAUDE.mdnetbox_proxbox/views/CLAUDE.mdnetbox_proxbox/views/endpoints/CLAUDE.mdtests/CLAUDE.md