Skip to content

Fix production bugs - #425

Merged
SchoolGuy merged 5 commits into
masterfrom
fix/api-remotepower-suggest-ip-bugs
Aug 14, 2026
Merged

Fix production bugs#425
SchoolGuy merged 5 commits into
masterfrom
fix/api-remotepower-suggest-ip-bugs

Conversation

@SchoolGuy

@SchoolGuy SchoolGuy commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

AI found a couple of bugs that I wasn't able to spot. The fixes align with my own retrospective investigations. The generated tests are sound and this should aid in making Orthos 2 more stable.

This is a split-out from #404 that cannot yet be merged. The bugs are not related to Cobbler itself.

netaddr.IPAddress(int) infers IPv4 for any value that fits in 32 bits. For a
domain with a small-valued IPv6 network (e.g. this dev stack's "::1"),
suggest_host_ip's final candidate-address construction produced a bogus
dotted-decimal string like "0.0.0.2" instead of "::2".

This wasn't just cosmetic: Cobbler's XML-RPC rejected the resulting address
with ipaddress.AddressValueError, a real stack trace during
UpdateCobblerMachine whenever a new interface got an IPv6 address suggested
on such a domain. Passing the network's own version explicitly fixes it.
A migration years ago renamed RemotePowerType.device's stored value from
"rpower_device" to "rpowerdevice", but RemotePower.save()'s dispatch branch
was never updated to match - so it was permanently unreachable, and every
RemotePower backed by a RemotePowerDevice (a PDU) fell through to the final
"else" branch instead. That branch was itself broken (fence["switching_device"]
on a RemotePowerType instance, not a dict), so instead of a clean validation
error it crashed with TypeError: 'RemotePowerType' object is not subscriptable.

This is the model backing the usage map's "remotepower/fence" machine-edit
field, so creating/editing that configuration was completely broken.
AddMachineCommand.post() called new_machine.get_primary_networkinterface()
on a freshly constructed, unsaved Machine - self.networkinterfaces (a
reverse FK manager) cannot be queried before self.pk exists, so every call
to POST /api/machine/add raised ValueError. Fixing that alone surfaced a
second bug: new_machine.domain_set doesn't exist (Machine has no such
attribute), which was used to suggest interface IP addresses.

Save the machine first (which resolves fqdn_domain and gives it a primary
key), then build and attach the primary NetworkInterface using
new_machine.fqdn_domain. No test had ever covered this endpoint - it was
completely broken since a 2024-03-25 refactor moved mac_address off Machine
onto NetworkInterface.
@codacy-production

codacy-production Bot commented Aug 14, 2026

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 1 high · 5 minor

Alerts:
⚠ 6 issues (≤ 0 issues of at least minor severity)

Results:
6 new issues

Category Results
Documentation 5 minor
Security 1 high

View in Codacy

🟢 Metrics 8 complexity · 7 duplication

Metric Results
Complexity 8
Duplication 7

View in Codacy

🟢 Coverage 94.81% diff coverage · +0.49% coverage variation

Metric Results
Coverage variation +0.49% coverage variation (-1.00%)
Diff coverage 94.81% diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (e7a0a4c) 13434 7606 56.62%
Head commit (c4cbadb) 13496 (+62) 7707 (+101) 57.11% (+0.49%)

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 (#425) 77 73 94.81%

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.

POST /api/bmc/add/<fqdn>/ saved a BMC directly, bypassing Machine.save()'s
own "{system} systems cannot use a BMC" check entirely. That let an admin
attach a BMC to a machine whose System type disallows one, silently creating
an inconsistent state that then permanently blocked every future save() of
that machine with an uncaught ValidationError.
…vice

RemotePowerDevice.architecture and .domain are both non-nullable, but
RemotePowerDeviceAPIForm's Meta.fields covered neither, and nothing
resolved domain from fqdn the way the frontend's NetBox-backed creation
view does. Every POST /api/remotepowerdevice/add call raised
django.db.utils.IntegrityError - this endpoint was completely broken.

Added architecture as an explicit required field, and override save() to
resolve domain from fqdn before saving.
@SchoolGuy
SchoolGuy force-pushed the fix/api-remotepower-suggest-ip-bugs branch from 6ef8b47 to c4cbadb Compare August 14, 2026 11:44
@SchoolGuy
SchoolGuy merged commit 342674d into master Aug 14, 2026
13 of 14 checks passed
@SchoolGuy
SchoolGuy deleted the fix/api-remotepower-suggest-ip-bugs branch August 14, 2026 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant