NetBox Manufacturer & DeviceType auto-lifecycle - #446
Merged
SchoolGuy merged 7 commits intoAug 22, 2026
Conversation
Manufacturer.fetch_netbox() only ever updates a row that already exists with a netbox_id set - there's no code path that discovers a NetBox manufacturer Orthos2 doesn't know about yet and creates it. Resolves a NetBox manufacturer ID to a Manufacturer, creating it on first sight. Looks up by netbox_id first, falling back to name (unique) and backfilling netbox_id onto a match instead of creating a duplicate - required because migration 0044_initial_required_data.py seeds 28 Manufacturer rows (including "AMD") unlinked from NetBox. Manufacturer is the "higher" model in the Manufacturer/DeviceType hierarchy (one Manufacturer has many DeviceTypes), so it gets its own resolver that DeviceType's equivalent method will delegate to.
Machine.fetch_netbox()/compare_netbox() and the "Add via NetBox ID" flow never populate device_type, even though NetBox's device payload includes a full nested device_type object - there was no code path that discovers a NetBox DeviceType Orthos2 doesn't know about yet and creates it. Resolves a NetBox device-type ID to a DeviceType, delegating manufacturer resolution to Manufacturer.get_or_create_from_netbox(). Looks up by netbox_id first (short-circuiting before any NetBox call), falling back to (name, manufacturer) and backfilling netbox_id onto a match instead of creating a duplicate - DeviceType has no DB-level uniqueness constraint, but a manufacturer shouldn't end up with two rows for what NetBox considers the same model.
AddMachineFormView.form_valid() fetched the NetBox device payload (which includes a full nested device_type object) but discarded it, leaving device_type unset for both newly-created machines and existing machines matched by fqdn. Wire in DeviceType.get_or_create_from_netbox() for both paths. Virtual machines have no device_type in NetBox, so this only applies to the "device" object type.
fetch_netbox() synced comment/serial_number/product_code and network interfaces/BMC but never touched device_type, even though the fetched device payload includes a full nested device_type object. Re-resolve via DeviceType.get_or_create_from_netbox() whenever it's unset or the linked DeviceType's netbox_id no longer matches what NetBox reports - covers both first-sync and NetBox-side device-type changes. Virtual machines have no device_type in NetBox, so this is a no-op for them.
Delete Manufacturer/DeviceType rows no longer referenced by any Machine or Enclosure. DeviceType is cleaned up first since DeviceType.manufacturer is on_delete=CASCADE - a Manufacturer only becomes orphaned once all its DeviceTypes are gone, and both cleanups run in the same execute() so a Manufacturer orphaned by this same pass is deleted immediately rather than waiting for the next run. Registered as a DailyTask (daily.py, tasks/__init__.py, registry.py, dailytasks.json fixture) alongside DailyNetboxFetch, following the same pattern. Note: migration 0044_initial_required_data.py seeds 28 Manufacturer rows without any DeviceType attached - on a deployment that hasn't created DeviceTypes for them yet, enabling this task will delete all of them the first time it runs, as requested.
If the taskmanager process is killed/restarted mid-execution, the in-memory running_threads dict that would normally clear a task's running flag (via _check_threads()) is lost, leaving the DB row stuck at running=True forever - SingleTask.get_single_tasks() only picks up running=False rows, and DailyTask's "Execute Now" action refuses to run a task that's (stale-)marked as already running. Reset every DailyTask/SingleTask still marked running=True the moment TaskExecuter.run() starts: a freshly-started process tracks no threads yet, so anything still flagged running in the database is necessarily stale, not actually in progress.
Complements the taskmanager's own startup auto-heal: for a task that's genuinely wedged while the taskmanager process is still alive (rather than crashed), a superuser previously had no way to clear a stuck 'running' flag on a SingleTask or DailyTask from the UI. Adds a danger-styled toggle button to both detail pages' action bars.
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| Documentation | 26 minor |
🟢 Metrics 69 complexity · 21 duplication
Metric Results Complexity 69 Duplication 21
🟢 Coverage 99.78% diff coverage · +0.82% coverage variation
Metric Results Coverage variation ✅ +0.82% coverage variation (-1.00%) Diff coverage ✅ 99.78% diff coverage Coverage variation details
Coverable lines Covered lines Coverage Common ancestor commit (5c58b70) 23634 17737 75.05% Head commit (c905edf) 24091 (+457) 18277 (+540) 75.87% (+0.82%) Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch:
<coverage of head commit> - <coverage of common ancestor commit>Diff coverage details
Coverable lines Covered lines Diff coverage Pull request (#446) 460 459 99.78% Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified:
<covered lines added or modified>/<coverable lines added or modified> * 100%
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
To enable automatic creation and deletion of Manufacturers and Device Types, Orthos 2 is now capable of creating them during device import and on a "Fetch NetBox" task. Furthermore, they get automatically cleaned up after the last machine or enclosure stops referencing them.
Lastly, this PR contains a bugfix for the TaskManager to clear stale tasks both automatically on startup and manually with a "Danger"-colored button.