Remove everything deprecated by the earlier steps.
OSDriver.ROLE stops defaulting to "linux"; each OS driver states its own. Today napalm-bsd inherits "linux".
Split models.py (1160 lines, 94 types) by area.
Type the remaining Dict[str, Any] role returns (phone, media, send_wake_on_lan).
Declare what drivers already offer undeclared: get_networks, search_packages, first_boot_pending, the base-system entry of an update list (napalm-bsd's BASE_SYSTEM). get_device_warnings is declared as facts only.
install_package/uninstall_package declare None, but napalm-linux returns {success, output} and callers read it. Declare the result.
No docstring, string or default names an application (rule test). Today about 30 docstrings say what netOrk does with a value.
The README shrinks to the concepts; reader details move with the readers.
Part of NetOrk/netork#1105. Plan: NAPALM/napalm-device-types docs/STRUCTURE.md (branch docs/structure-plan).
Prio P4: cleanup once everything above has landed.
- Remove everything deprecated by the earlier steps.
- `OSDriver.ROLE` stops defaulting to `"linux"`; each OS driver states its own. Today napalm-bsd inherits `"linux"`.
- Split `models.py` (1160 lines, 94 types) by area.
- Type the remaining `Dict[str, Any]` role returns (`phone`, `media`, `send_wake_on_lan`).
- Declare what drivers already offer undeclared: `get_networks`, `search_packages`, `first_boot_pending`, the base-system entry of an update list (napalm-bsd's `BASE_SYSTEM`). `get_device_warnings` is declared as facts only.
- `install_package`/`uninstall_package` declare `None`, but napalm-linux returns `{success, output}` and callers read it. Declare the result.
- No docstring, string or default names an application (rule test). Today about 30 docstrings say what netOrk does with a value.
- The README shrinks to the concepts; reader details move with the readers.
Part of NetOrk/netork#1105. Plan: NAPALM/napalm-device-types `docs/STRUCTURE.md` (branch `docs/structure-plan`).
Prio P4: cleanup once everything above has landed.
Added to 5.0 (decided by Christian, 2026-10-17): key the virtual IP reading by mechanism as data.
Proposed by netork-d4 during NetOrk/netork#1121. Today VirtualIpsDict has one field per mechanism (vip_manager, keepalived, and since 4.10 carp, NotRequired). Each new HA mechanism (VRRP on a switch, pfSense CARP, Proxmox HA, ucarp) would change the contract again, and the field names are product names.
Change
VirtualIpsDict → Dict[str, Optional[List[VirtualIpDict]]], keyed by VirtualIpDict.mechanism ("vip-manager", "keepalived", "carp"). The key and each entry's mechanism are the same string, so today's two spellings (vip_manager / vip-manager) go away.
The vocabulary stays typed: the known mechanisms as constants or a Literal, so a typo does not pass mypy unnoticed.
Semantics, written into the docstring: a key a driver sends with a list = looked ([] = none there); None = tried but could not read; a key it does not send = does not read that mechanism. A consumer keeps what it knew for both of the last two. A driver must send every mechanism it read, even when empty, or stale members are never removed.
A driver sends only what it reads: OPNsense {"carp": [...]}, the Linux reader {"vip-manager": ..., "keepalived": ...}.
Why with 5.0 and not before: it breaks napalm-linux (or napalm-unix after #35, where VirtualIpsMixin moves anyway), napalm-opnsense and netOrk's core/virtual_ips/store.py at once. 5.0 breaks the same places, so the cost is paid once.
netOrk side (with the pin bump to 5.0):store.MECHANISMS goes; the store reads both shapes for as long as satellites can send the old one (old keys map vip_manager → vip-manager).
**Added to 5.0 (decided by Christian, 2026-10-17): key the virtual IP reading by mechanism as data.**
Proposed by netork-d4 during NetOrk/netork#1121. Today `VirtualIpsDict` has one field per mechanism (`vip_manager`, `keepalived`, and since 4.10 `carp`, NotRequired). Each new HA mechanism (VRRP on a switch, pfSense CARP, Proxmox HA, ucarp) would change the contract again, and the field names are product names.
**Change**
- `VirtualIpsDict` → `Dict[str, Optional[List[VirtualIpDict]]]`, keyed by `VirtualIpDict.mechanism` (`"vip-manager"`, `"keepalived"`, `"carp"`). The key and each entry's `mechanism` are the same string, so today's two spellings (`vip_manager` / `vip-manager`) go away.
- The vocabulary stays typed: the known mechanisms as constants or a `Literal`, so a typo does not pass mypy unnoticed.
- Semantics, written into the docstring: a key a driver sends with a list = looked (`[]` = none there); `None` = tried but could not read; a key it does not send = does not read that mechanism. A consumer keeps what it knew for both of the last two. A driver must send every mechanism it read, even when empty, or stale members are never removed.
- A driver sends only what it reads: OPNsense `{"carp": [...]}`, the Linux reader `{"vip-manager": ..., "keepalived": ...}`.
**Why with 5.0 and not before:** it breaks napalm-linux (or napalm-unix after #35, where `VirtualIpsMixin` moves anyway), napalm-opnsense and netOrk's `core/virtual_ips/store.py` at once. 5.0 breaks the same places, so the cost is paid once.
**netOrk side (with the pin bump to 5.0):** `store.MECHANISMS` goes; the store reads both shapes for as long as satellites can send the old one (old keys map `vip_manager` → `vip-manager`).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
OSDriver.ROLEstops defaulting to"linux"; each OS driver states its own. Today napalm-bsd inherits"linux".models.py(1160 lines, 94 types) by area.Dict[str, Any]role returns (phone,media,send_wake_on_lan).get_networks,search_packages,first_boot_pending, the base-system entry of an update list (napalm-bsd'sBASE_SYSTEM).get_device_warningsis declared as facts only.install_package/uninstall_packagedeclareNone, but napalm-linux returns{success, output}and callers read it. Declare the result.Part of NetOrk/netork#1105. Plan: NAPALM/napalm-device-types
docs/STRUCTURE.md(branchdocs/structure-plan).Prio P4: cleanup once everything above has landed.
Added to 5.0 (decided by Christian, 2026-10-17): key the virtual IP reading by mechanism as data.
Proposed by netork-d4 during NetOrk/netork#1121. Today
VirtualIpsDicthas one field per mechanism (vip_manager,keepalived, and since 4.10carp, NotRequired). Each new HA mechanism (VRRP on a switch, pfSense CARP, Proxmox HA, ucarp) would change the contract again, and the field names are product names.Change
VirtualIpsDict→Dict[str, Optional[List[VirtualIpDict]]], keyed byVirtualIpDict.mechanism("vip-manager","keepalived","carp"). The key and each entry'smechanismare the same string, so today's two spellings (vip_manager/vip-manager) go away.Literal, so a typo does not pass mypy unnoticed.[]= none there);None= tried but could not read; a key it does not send = does not read that mechanism. A consumer keeps what it knew for both of the last two. A driver must send every mechanism it read, even when empty, or stale members are never removed.{"carp": [...]}, the Linux reader{"vip-manager": ..., "keepalived": ...}.Why with 5.0 and not before: it breaks napalm-linux (or napalm-unix after #35, where
VirtualIpsMixinmoves anyway), napalm-opnsense and netOrk'score/virtual_ips/store.pyat once. 5.0 breaks the same places, so the cost is paid once.netOrk side (with the pin bump to 5.0):
store.MECHANISMSgoes; the store reads both shapes for as long as satellites can send the old one (old keys mapvip_manager→vip-manager).