feat(dwdm): optical channels, port function, and object templates - #77
Open
iddocohen wants to merge 4 commits into
Open
feat(dwdm): optical channels, port function, and object templates#77iddocohen wants to merge 4 commits into
iddocohen wants to merge 4 commits into
Conversation
Deploying schema-library with
|
| Latest commit: |
4c38bc4
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://b31bc70e.schema-library.pages.dev |
| Branch Preview URL: | https://ic-add-optical-u5o17.schema-library.pages.dev |
iddocohen
marked this pull request as ready for review
August 13, 2026 14:31
Model a wavelength booked end to end over a span, and stop optical
measurements from being unstorable: the Number attribute kind is exposed
as GraphQL BigInt, so a fractional value is rejected outright rather than
rounded. Verified on Infrahub 1.10.6 -- 193.1 fails with "Expected value
of type 'BigInt', found 193.1".
extensions/dwdm:
- Add DcimOpticalChannel: one wavelength between two endpoints, with its
A-to-Z and Z-to-A channels, its line ends and the cables it crosses.
- Give WDM interfaces separate transmit and receive channels, so
single-fibre WDM is expressed as data rather than as a naming
convention.
- Tie channels to the ITU grid via grid, band, frequency_ghz and
wavelength_pm.
- Namespace the front_interfaces and rear_interfaces identifiers to the
OpticalMultiplexer node pair. The bare strings are also used by
extensions/patch_panel, and a shared identifier is a trap for the next
person to reuse.
- Add the extensions/cable dependency.
experimental/optical_transport:
- Rescale every physical quantity to a unit that is exact as an integer:
THz to GHz, nm to pm, dBm to tenths of a dBm, km to m, dB to tenths of
a dB.
- Split links into links_a and links_z, and add the missing inverse
relationships (mux_assignments, services, path_segments, roadm_degrees,
amplifier_modules, optical_services).
- Record why the OpticalPath roll-ups cannot be computed attributes.
Relationship shapes, in both files:
- Replace kind: Component on the three cardinality: one relationships
(OpticalMultiplexer.rear_interface, OpticalService.primary_path and
OpticalService.backup_path) with kind: Attribute plus on_delete:
cascade. Component is documented as pairing with cardinality: many, so
the combination misread as a collection.
This is a convention fix, not a behaviour change. Both shapes were
loaded onto separate branches of a live instance and behave
identically: each rejects a second peer with the same message ("has 2
peers for optical_multiplexer__rear_interfaces, maximum of 1 allowed"),
and each cascade-deletes the child with its parent. The explicit
on_delete: cascade is what keeps that second property, since Infrahub
derives cascade for Component automatically and dropping Component
without it would have silently lost the cascade.
tasks/docs.py:
- Keep the home page's trailing newline, which Jinja2 strips and
markdownlint MD047 then flags.
Also ignores .claude/settings.local.json.
iddocohen
force-pushed
the
ic/add-optical-u5o17
branch
from
August 13, 2026 15:05
e4b4eab to
2272432
Compare
iddocohen
marked this pull request as draft
August 13, 2026 15:06
iddocohen
marked this pull request as ready for review
August 13, 2026 15:19
Add an optional optical_function dropdown on DcimGenericOadmInterface, so both front and rear interfaces can record what a port actually does in the optical path. Front-vs-rear only expresses client-vs-line; it cannot label express, expansion, monitor, OSC, amplifier or OTDR ports, which forced vendor port names to be parsed to tell them apart. The vocabulary is functional and vendor-agnostic, so it holds for passive filters and active line gear alike. Enable generate_template on DcimOpticalMultiplexer. A mux model is a fixed shape, so cloning a curated example beats rebuilding every port by hand. Switch rear_interface from Attribute + on_delete: cascade to Component. Only Component children are carried into an object template: as Attribute no TemplateDcimOadmRearInterface was generated and every mux cloned from a template came out with no line port. Component on a singular child holds up, a second peer is rejected with "maximum of 1 allowed" and deleting the mux still takes the rear interface with it.
Reference pages are fully generated, and the only writable prose slot was the metadata description, which also feeds the home page card and so is a poor place for a longer list. Schema YAML comments do not reach the docs either, since the generator dumps parsed YAML. Add two optional metadata keys, use_cases and not_covered, rendered as a "Use cases" section. Extensions that omit both render nothing, so this is additive and leaves the other pages untouched. DWDM is the first user and points readers at experimental/optical_transport for the active line gear it deliberately does not model.
These six pages drifted from their schema files: earlier changes edited the YAML without running invoke docs.generate, so the rendered tables still describe the previous shape. Nothing here is hand-written, it is all generator output catching up (for example sfp now shows InterfacePhysical where the schema had already moved off DcimInterface). CI does not catch this. The check-documentation job runs "git diff --exit-code -- docs/reference/" from the repo root, but the pages live at docs/docs/reference/, so the path matches nothing and the check passes unconditionally. The wrong path is left alone here, since fixing it would make the job start failing on anything still stale elsewhere.
Contributor
|
I will agree to it for the moment, there is a bigger work/clean-up to be done to unify the library as we have it as experimental and as extension with slight difference. |
BeArchiTek
approved these changes
Aug 24, 2026
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.
What
Adds end-to-end optical channel modelling to
extensions/dwdm, and rescales the physicalquantities in
experimental/optical_transportto units that are exact as integers.Why the unit rescale
Infrahub's
Numberattribute is exposed as GraphQLBigInt. A fractional value is notrounded, it is rejected:
193.1THz could not be stored at all. Every quantity is now scaled to an exact integer andcarries its unit in the name: THz to GHz, nm to pm, dBm to tenths, km to m, dB to tenths.
frequency_ghz,wavelength_pm,tx_power_ddbm,total_distance_m,loss_ddb.extensions/dwdm
DcimOpticalChannel— one wavelength booked between two endpoints, carrying itsA-to-Z and Z-to-A grid points, its line ends, and the cables it crosses. Only new node in
this PR.
a naming convention.
DcimWdmChannelviagrid,band,frequency_ghz,wavelength_pm.The old
wdm_type,wavelengthandfrequencyare deprecated, not removed.optical_functiononDcimGenericOadmInterface:line,client,express,expansion,band,monitor,osc,amplifier,otdr. Front-vs-rear saysclient-vs-line but cannot express pass-through, upgrade stages, taps, supervisory or OTDR.
Vocabulary is functional and vendor-agnostic. Note
expansion(upgrade port, labelled EXPby some vendors) and
express(pass-through) are different functions.generate_template: trueonDcimOpticalMultiplexer. A mux model is a fixed shape, socloning a curated example beats rebuilding every port by hand.
front_interfaces/rear_interfacesbecomeoptical_multiplexer__*. The bare strings are also used byextensions/patch_panel.extensions/cabledependency.experimental/optical_transport
No nodes added or removed.
FiberLink.endpointssplit intoa_end/z_end;OpticalNode.linksintolinks_a/links_z;ChannelMapping.segmentintopath_segments.mux_assignments,services,transponder_modules,optical_services,roadm_degrees,amplifier_modules.OpticalPathroll-ups cannot be computed attributes: a computedattribute must be
TextorURL, and Jinja2 cannot see a cardinality-many relationship.Relationship shapes
OpticalService.primary_pathand.backup_pathmove fromkind: Component/cardinality: onetokind: Attribute+on_delete: cascade.Componentpairs withcardinality: manyby convention, so the combination read as a collection when it is not one.The explicit
on_delete: cascadepreserves the behaviour Infrahub derives fromComponentautomatically.
OpticalMultiplexer.rear_interfacestaysComponent. OnlyComponentchildren arecarried into an object template. As
Attribute, measured on a live instance: noTemplateDcimOadmRearInterfacewas generated, and every mux cloned from a template came outwith
rear_interface: NULL, silently missing its COM port. All three properties hold eitherway except that last one:
Attribute+cascadeComponent/onemaximum of 1 allowedThis leaves
dwdmandoptical_transportusing different shapes for the same pattern.Deliberate: only
dwdmhas templates. If reviewers prefer the convention, the alternative isdropping
generate_templatefrom this node.primary_path/backup_pathwere deliberately not collapsed into onepathscollection.Two singular relationships enforce "exactly one primary, at most one backup" in the schema
rather than in a check.
Docs
tasks/docs.pygains two optional.metadata.ymlkeys,use_casesandnot_covered,rendered as a
## Use casessection. Extensions omitting both render nothing, so the other 40pages are unaffected by the template itself. DWDM is the first user.
Six unrelated reference pages are regenerated here (
sfp,security,lag,mlag,dcim,circuit_contract, plus ahome.mdxrow). They are not edits. They are pre-existingdrift on
main: for examplesfp.mdxstill namedDcimInterfacewhere the schema has saidInterfacePhysicalsince #74. The generator rewrites all 52 pages in one pass, and this PR hasto run it, so the backlog comes along. Reverting them by hand does not hold: I confirmed that
any
invoke docs.generatereproduces them exactly.Root cause:
ci.yml:201runsgit diff --exit-code -- docs/reference/from the repo root,but the pages live at
docs/docs/reference/. The path matches nothing, so the gate has passedunconditionally since #65. Left unfixed here — correcting the path would start failing CI
on anything still stale elsewhere, which is a bigger cleanup than this PR should carry.
Testing
Loaded onto a live Infrahub 1.10.6 instance.
.metadata.ymlrecords thatoptical_transportis not designed to be loaded with
dwdm, so each went onto its own branch off abase-onlymain. All loads clean./api/schema: every relationship resolved to a singlebidirectional edge per identifier, with
kind,cardinality,optional,on_deleteas written.frequency_ghz192100,wavelength_pm1560606,band.start_frequency_ghz191300,grid.reference_frequency_ghz193100.channel_namerendersCH21.DcimOpticalService(2 transponders, channel, primary and backup path) traversedboth ways. A second service claiming the same primary path is rejected. Deleting the service
cascade-deleted both paths.
optical_functionapplied as a real migration over pre-existing data:schema checkdry runreports one added attribute,
changed: {}/removed: {}; existing interfaces survive withnull; all nine choices accepted, out-of-vocabulary rejected.
Template*kinds generated. Two muxes cloned from one templateeach got 3 front ports and the rear port, with
optical_functionand grid links intact.8 distinct port objects across 2 clones, so real copies rather than shared references.
invoke linter.yamlclean repo-wide. Both schema files validate againstschema.infrahub.app/infrahub/schema/latest.jsonwith 0 errors.CI does not cover any of the above:
tasks/schemas.py:92skipsexperimental/unlessTEST_EXPERIMENTALis set, and no workflow sets it.Known issues, left alone
ci.yml:201docs-freshness path bug, above.experimental/optical_transportandextensions/topologyboth render toreference/topology.mdx, so one page silently overwrites the other. Not triggered by this PR..metadata.ymlis not in the canonical forminvoke linter.sort-metadataproduces; runningit rewrites 87 lines. Nothing in CI checks it, and the reflow would bury this diff.