Skip to content

Implement Openconfig NTP provider - #517

Open
adamtrizuljak-sap wants to merge 4 commits into
mainfrom
feat/openconfig-ntp
Open

adamtrizuljak-sap wants to merge 4 commits into
mainfrom
feat/openconfig-ntp

Conversation

@adamtrizuljak-sap

@adamtrizuljak-sap adamtrizuljak-sap commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Work in progress

  • Add OpenConfig provider implementation for the NTP resource (internal/provider/openconfig/ntp.go) and a gnmi testdata file (test/gnmi/testdata/openconfig/ntp.txtar).
  • Add optional field NTPSpec.SourceAddress and validation logic (see below)
  • Get the IP address of the NTPSpec.SourceInterface from the device using the GRPC client and use it to populate the source-address field in Openconfig
  • Add a simple Containerlab setup with one SRLinux node + the associated network-operator Device and NTP resources

Applying examples/openconfig-containerlab/kubernetes/01-devices/v1alpha1-leaf1-clab-ntp.yaml produces the following config in SRLinux:

--{ + running }--[  ]--
A:admin@srl# info system ntp | as json
{
  "admin-state": "enable",
  "server": [
    {
      "address": "de.pool.ntp.org",
      "prefer": true,
      "network-instance": "mgmt",
      "source-address": "172.20.20.2"
    },
    {
      "address": "pool.ntp.org",
      "network-instance": "mgmt",
      "source-address": "172.20.20.2"
    }
  ]
}

Cisco vs Openconfig compatibility issue (solved)

NTPSpec defines the SourceInterfaceName field https://github.com/ironcore-dev/network-operator/blob/main/api/core/v1alpha1/ntp_types.go#L36. Openconfig has something similar source-address https://openconfig.net/projects/models/schemadocs/yangdoc/openconfig-system.html#system-ntp-servers-server-config-source-address

A way to handle it would be to look up the interface given by SourceInterfaceName , get its IPv4 address and put it into source-address. Does it make sense? Do you usually do such operations, or do you keep the provider code clean from reading any additional k8s resources?

Other way would be to just ignore SourceInterfaceName and not pass it into the Openconfig struct, or even throw a apistatus.FieldViolation saying that it's unsupported

Solution

After discussion we decided to do the original proposal and obtain the IP address from the interface. However, if the management interface is used for NTP we can't obtain the address from an Interface resource, because we don't create such resource for the management interface. Therefore the provider reads the interface state directly from the device over GRPC and uses its IP address to populate the source-address field.

This solution does not change the NTPSpec and should work with any SourceInterfaceName that has an IP address (either manually configured, or obtained from DHCP).

Previous solution - abandoned

Discussed with @nikatza and @rgildein

Since both fields are optional, the change will be backwards-compatible with the previous NTPSpec and the generated custom resources.

@hardikdr hardikdr added the area/switch-automation Automation processes for network switch management and operations. label Aug 22, 2026
@hardikdr hardikdr added this to Roadmap Aug 22, 2026
@adamtrizuljak-sap
adamtrizuljak-sap marked this pull request as ready for review September 3, 2026 14:21
Comment thread test/gnmi/testdata/openconfig/ntp.txt Outdated
Comment thread examples/openconfig-containerlab/kubernetes/01-devices/kustomization.yaml Outdated
Comment thread api/core/v1alpha1/ntp_types.go Outdated
Comment thread api/core/v1alpha1/ntp_types.go Outdated
Comment thread internal/provider/openconfig/ntp.go Outdated
Comment thread internal/provider/openconfig/ntp.go Outdated
@adamtrizuljak-sap
adamtrizuljak-sap force-pushed the feat/openconfig-ntp branch 2 times, most recently from 6974f26 to edf5a26 Compare September 7, 2026 15:01
- Add OpenConfig provider implementation for the NTP resource (`internal/provider/openconfig/ntp.go`) and a gnmi testdata file (`test/gnmi/testdata/openconfig/ntp.txtar`)
- Get the IP address of the `NTPSpec.SourceInterface` from the device using the GRPC client and use it to populate the `source-address` field in Openconfig
- Add a simple Containerlab setup with one SRLinux node + the associated network-operator `NTP` resource

If the management interface is used for NTP we can't obtain the address from an `Interface` resource, because we don't create such resource for the management interface.
Therefore the provider reads the interface state directly from the device over GRPC and uses its IP address to populate the `source-address` field.

Signed-off-by: Adam Trizuljak <adam.trizuljak@sap.com>

@nikatza nikatza left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some minor comments, happy to discuss them if needed :) 🚀

Comment thread api/core/v1alpha1/ntp_types.go Outdated
@@ -0,0 +1,19 @@
apiVersion: networking.metal.ironcore.dev/v1alpha1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fear these new files included in this folder as they don't really fit well here in this PR. I think the examples folder is reserved to more complex scenarios. If that is OK for you we could remove them and clarify in our weekly. What do you think?

@adamtrizuljak-sap adamtrizuljak-sap Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created this file because Openconfig requires different settings from config/samples/v1alpha1_ntp.yaml.

As I wrote here #517 (comment), my idea is to have ready-to-go samples for all providers which can be used during development for testing against a Containerlab setup or similar. If I only have config/samples/v1alpha1_ntp.yaml in the repo, I would need to overwrite it each time, discard the changes afterwards (and pay attention to not commit it) and do this for every resource that differs -> not a very streamlined and uniform development workflow.

Do you have an idea for better placement of such samples? Maybe move config/samples/ into something like config/samples/common and place this file into config/samples/openconfig?

}

func (a *interfaceAddrs) XPath() string {
return fmt.Sprintf("openconfig-interfaces:interfaces/interface[name=%s]/subinterfaces/subinterface[index=0]/openconfig-if-ip:ipv4/addresses", a.ifName)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have two hard-coded elements here: the index (0) and the AFI (IPv4). I think we should be able to fetch IPv6 or indicate the address family we want. Same goes for the index. What we could do is add these fields in interfaceAddrs (with tag json:"-") and build our xpath using those values.

If so the provider should be changed accordingly, e.g., use index 0 when the interface name matches some constraints (or just document why 0 is hard-coded). For the IPv4 and IPv6 AFI: you could make that dependent on the AFI of the NTPServers in the spec.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a simple lookup to get the first IP address of the interface given by NTPSpec.SourceInterfaceName, which we did to avoid adding the NTPSpec.SourceAddress field. I am not sure how to include the information (especially the interface index) without again modifying NTPSpec...

}

// interfaceIPAddr retrieves the first IPv4 address from the state of the named interface.
func (p *Provider) interfaceIPAddr(ctx context.Context, name string) (string, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to get IPv6 addresses too :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could do it, but in general we don't support IPv6 in network-operator?

Comment thread internal/provider/openconfig/interface.go Outdated
Comment thread Tiltfile Outdated
Comment on lines +210 to +211
k8s_yaml('./examples/openconfig-containerlab/kubernetes/01-devices/v1alpha1-leaf1-clab-ntp.yaml')
k8s_resource(new_name='ntp-clab', objects=['ntp-clab:ntp'], trigger_mode=TRIGGER_MODE_MANUAL, auto_init=False, labels=['containerlab'])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would propose to leave the existing resource from samples and keep the tilt file compact.

Comment thread api/core/v1alpha1/ntp_types.go Outdated
Comment thread internal/provider/openconfig/interface.go Outdated
Comment thread internal/provider/openconfig/ntp.go
Comment thread Tiltfile Outdated
Comment thread internal/provider/openconfig/ntp.go Outdated
Signed-off-by: Adam Trizuljak <adam.trizuljak@sap.com>
Signed-off-by: Adam Trizuljak <adam.trizuljak@sap.com>
Signed-off-by: Adam Trizuljak <adam.trizuljak@sap.com>
@github-actions

Copy link
Copy Markdown

Merging this branch will decrease overall coverage

Impacted Packages Coverage Δ 🤖
github.com/ironcore-dev/network-operator/internal/provider/openconfig 9.42% (-0.39%) 👎

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/ironcore-dev/network-operator/internal/provider/openconfig/interface.go 10.22% (-0.72%) 137 (+9) 14 123 (+9) 👎
github.com/ironcore-dev/network-operator/internal/provider/openconfig/ntp.go 0.00% (ø) 16 (+16) 0 16 (+16)

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/switch-automation Automation processes for network switch management and operations. size/L

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants