Skip to content

Improve PID and Versioning Node Data Retrieval#55

Merged
joshhalley merged 15 commits intodevelopfrom
pr/johalley/node_update
Feb 7, 2026
Merged

Improve PID and Versioning Node Data Retrieval#55
joshhalley merged 15 commits intodevelopfrom
pr/johalley/node_update

Conversation

@joshhalley
Copy link
Contributor

@joshhalley joshhalley commented Feb 5, 2026

Description

This PR enhances the Kubernetes node information for Cisco IOS-XE devices by dynamically fetching device details from the network device at initialization time using RESTCONF and the openconfig-platform YANG model. Addressing issue #51 .

Changes:

  • Added GetDeviceInfo method to the CiscoKubernetesDeviceDriver interface
  • Implemented device info fetching from /restconf/data/openconfig-platform:components during CheckConnection
  • Extracts serial number, software version, and product ID from the CHASSIS component
  • Parses the verbose software-version string to extract just the numeric version (e.g., 17.18.2)
  • Populates Kubernetes node fields:
    • MachineID / SystemUUID → Device serial number
    • KernelVersion → IOS-XE version number
    • OSImageCisco IOS-XE <ProductID>

Before:

NAME          VERSION   OS-IMAGE      KERNEL-VERSION
cat9k-node   v1.0.0    Cisco IOS-XE  (empty)

After:

NAME          VERSION   OS-IMAGE                 KERNEL-VERSION
cat9k-node   v1.0.0    Cisco IOS-XE C9300-24P   17.18.2

Test Results

Node and Pod details are populating correctly during provision:

NAME       STATUS   ROLES           AGE    VERSION        INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
ubuntu17   Ready    control-plane   7d4h   v1.34.3+k3s1   10.0.2.2      <none>        Ubuntu 22.04.5 LTS   5.15.0-164-generic   containerd://2.1.5-k3s1
cat9k-node   Ready    <none>          0s     v1.0.0                       <none>        Cisco IOS-XE C9300-24P   17.18.2              cisco.app.hosting://1.0
cisco@ubuntu17:~$ kubectl get pods -o wide -w
NAME                                    READY   STATUS    RESTARTS   AGE     IP             NODE          NOMINATED NODE   READINESS GATES
cisco-virtual-kubelet-75cdbf545-m6xgz   1/1     Running   0          10m     10.0.0.100     ubuntu17      <none>           <none>
iox-xe-hello-app-pod                    1/1     Running   0          8m28s   192.168.99.6   cat8kv-node   <none>           <none>

Type of Change

  • Bug Fix
  • New Feature
  • Breaking Change
  • Refactor
  • Documentation
  • Other (please describe)

Checklist

  • I have read the contributing guidelines
  • Existing issues have been referenced (where applicable)
  • I have verified this change is not present in other open pull requests
  • Functionality is documented
  • All code style checks pass
  • New code contribution is covered by automated tests
  • All new and existing tests pass

Files Changed (6):

File Changes
internal/drivers/common/types.go Added DeviceInfo struct
internal/drivers/factory.go Added GetDeviceInfo to interface
internal/drivers/iosxe/driver.go Implemented fetchDeviceInfo, parseVersionNumber, GetDeviceInfo
internal/drivers/fake/driver.go Added stub GetDeviceInfo
internal/provider/defaults.go Updated to use DeviceInfo for node fields
cmd/virtual-kubelet/root.go Wire up driver and pass deviceInfo to node spec

@joshhalley joshhalley changed the title Pr/johalley/node update Improve PID and Versioning Node Data Retrieval Feb 5, 2026
Copy link
Contributor

Choose a reason for hiding this comment

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

apologies - I renamed this file in the previous merge :-o

return nil
}

func (d *XEDriver) fetchDeviceInfo(ctx context.Context) *common.DeviceInfo {
Copy link
Contributor

@cunningr cunningr Feb 6, 2026

Choose a reason for hiding this comment

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

I wonder now if openconfig is the way to go or not. We can't use it for anything else, and now I see the code we either accept the one-off JSON parsing pattern or import a bunch of openconfig YANG models and bindings. Do we know what the alternative 'native' model would be? Maybe that is better supported across cisco XE (driver scope) devices and suit our needs better?

For example these two seem to return something useful for both c8kv and c9k and possibly contains everything we need?:

/restconf/data/Cisco-IOS-XE-device-hardware-oper:device-hardware-data

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I shifted (for this version) across to the native model, unfortunately, it still populates the version field as a large string which requires regexp parsing:

      "device-system-data": {
        "current-time": "2026-02-06T14:39:00+00:00",
        "boot-time": "2026-02-05T19:54:23+00:00",
        "software-version": "Cisco IOS Software [IOSXE], Catalyst L3 Switch Software (CAT9K_IOSXE), Version 17.18.2, RELEASE SOFTWARE (fc3)\nTechnical Support: http://www.cisco.com/techsupport\nCopyright (c) 1986-2025 by Cisco Systems, Inc.\nCompiled Fri 19-Dec-25 03:36 by mcpre",
        "rommon-version": "IOS-XE ROMMON",
        "last-reboot-reason": "Reload Command",
        "reason-severity": "normal",
        "unsaved-config": true,
        "reload-history-support": [null],
        "reload-history": {
          "rl-history": [
            {
              "reload-category": "rc-rld",
              "reload-desc": "Reload Command",
              "reload-time": "2026-02-05T19:54:36+00:00",
              "reload-severity": "normal",
              "sw-ver": "",
              "ha-role": "ha-role-unknown",
              "crash-data-file": ""
            }
          ],
          "fru-type": "device-hardware-fru-rp",
          "fru-id": 0
        },
        "mac-address": "34:73:2d:81:67:80"
      }
    }
  }
}

"syscall"

"github.com/cisco/virtual-kubelet-cisco/internal/config"
"github.com/cisco/virtual-kubelet-cisco/internal/drivers"
Copy link
Contributor

Choose a reason for hiding this comment

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

by design, i don' think we should be importing driver code here. Could we provide a skeleton device info and then update once the provider initialises the driver? We need to do this anyway for node lifecycle maintenance. We currently have an unimplemented nodeProvider that I suspect caters for this.

@joshhalley joshhalley force-pushed the pr/johalley/node_update branch 2 times, most recently from 803d8ba to 5aad77a Compare February 6, 2026 14:17
@joshhalley
Copy link
Contributor Author

PR Comment Review Summary

Based on my review of PR #55 (pr/johalley/node_update), here are the 4 comments and their status:


Comment 1: File Rename Conflict

Author: @cunningr
File: examples/configs/device-configs.yaml
Comment: "apologies - I renamed this file in the previous merge :-o"

Status:ADDRESSED
The branch has been rebased onto develop, resolving the file rename conflict.


Comment 2: Use Native YANG Model Instead of OpenConfig

Author: @cunningr
File: internal/drivers/iosxe/driver.go
Comment: Suggested using Cisco-IOS-XE-device-hardware-oper:device-hardware-data instead of OpenConfig, as it's better supported across Cisco XE devices.

Status:ADDRESSED
The code now uses the native YANG mode, however the issues with the long string that requires a regexp is still present, maybe in other platforms this is handled more elegantly:

err := d.client.Get(ctx, "/restconf/data/Cisco-IOS-XE-device-hardware-oper:device-hardware-data", &resp, json.Unmarshal)

Comment 3: Remove Driver Import from root.go

Author: @cunningr
File: cmd/virtual-kubelet/root.go
Comment: "by design, I don't think we should be importing driver code here. Could we provide a skeleton device info and then update once the provider initialises the driver? We need to do this anyway for node lifecycle maintenance. We currently have an unimplemented nodeProvider that I suspect caters for this."

Status:ADDRESSED

  • The drivers import has been removed from root.go
  • The NotifyNodeStatus pattern is now used in provider.go to update node info after driver initialization
  • GetInitialNodeSpec no longer requires DeviceInfo

Comment 4: Version String Parsing

Author: @joshhalley (your response to comment 2)
File: internal/drivers/iosxe/driver.go
Comment: Noted that the native model still returns a verbose version string requiring regex parsing.

Status:ADDRESSED
The parseVersionNumber function extracts just the version number (e.g., 17.18.2) from the verbose string:

func parseVersionNumber(fullVersion string) string {
    re := regexp.MustCompile(`Version\s+(\d+\.\d+\.\d+)`)
    matches := re.FindStringSubmatch(fullVersion)
    if len(matches) > 1 {
        return matches[1]
    }
    return fullVersion
}

Summary

@cunningr the branch is ready for re-review and merge after pushing the rebased changes.

OSImage: "Cisco IOSXE",
KernelVersion: "__cisco_ios__",
ContainerRuntimeVersion: "cisco.app.hosting",
Architecture: "amd64",
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if we should make this obvious that if we failed to populate this with proper information, we add values to indicate this information is bogus, like: "version_unknown" etc.

@joshhalley
Copy link
Contributor Author

Adjusted driver pattern, and further references in node outputs to be more representative (see below):

@cunningr - a ygot struct for XE-native would be helpful if you can share one

System Info:
  Machine ID:                 94ECAAA4TSM
  System UUID:                94ECAAA4TSM
  Boot ID:
  Kernel Version:             17.15.4
  OS Image:                   IOS-XE
  Operating System:           Cisco
  Architecture:               C8000V
  Container Runtime Version:
  Kubelet Version:
  Kube-Proxy Version:
PodCIDR:                      10.42.3.0/24
PodCIDRs:                     10.42.3.0/24
Non-terminated Pods:          (0 in total)
  Namespace                   Name    CPU Requests  CPU Limits  Memory Requests  Memory Limits  Age
  ---------                   ----    ------------  ----------  ---------------  -------------  ---
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests  Limits
  --------           --------  ------
  cpu                0 (0%)    0 (0%)
  memory             0 (0%)    0 (0%)
  ephemeral-storage  0 (0%)    0 (0%)
  storage            0         0
Events:
  Type    Reason                Age   From             Message
  ----    ------                ----  ----             -------
  Normal  CIDRAssignmentFailed  73s   cidrAllocator    Node cat8kv-node status is now: CIDRAssignmentFailed
  Normal  RegisteredNode        68s   node-controller  Node cat8kv-node event: Registered Node cat8kv-node in Controller
cisco@ubuntu17:~$ kubectl get nodes -o wide
NAME          STATUS   ROLES           AGE     VERSION        INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
cat8kv-node   Ready    <none>          2m18s                  192.0.2.30    <none>        IOS-XE               17.15.4              <unknown>
ubuntu17      Ready    control-plane   8d      v1.34.3+k3s1   10.0.2.2      <none>        Ubuntu 22.04.5 LTS   5.15.0-168-generic   containerd://2.1.5-k3s1

@cunningr
Copy link
Contributor

cunningr commented Feb 7, 2026

@joshhalley you can rebase off of this branch -> cunningr/models-update

@joshhalley joshhalley force-pushed the pr/johalley/node_update branch from d769ef6 to cbf9bde Compare February 7, 2026 17:01
Copy link
Contributor

@cunningr cunningr left a comment

Choose a reason for hiding this comment

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

LGTM

@joshhalley
Copy link
Contributor Author

Confirmed functionality with suggested enrichments:

cisco@ubuntu17:~$ kubectl get nodes -o custom-columns=NAME:.metadata.name,KUBELET-VERSION:.status.nodeInfo.kubeletVersion
NAME          KUBELET-VERSION
cat8kv-node   v1.11.0
ubuntu17      v1.34.3+k3s1
cisco@ubuntu17:~$ kubectl get nodes -o custom-columns=NAME:.metadata.name,KUBELET-VERSION:.status.nodeInfo.kubeletVersion -o wide
NAME          STATUS   ROLES           AGE   VERSION        INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
cat8kv-node   Ready    <none>          98s   v1.11.0        198.51.100.100   <none>        IOS-XE               17.18.2              <unknown>
ubuntu17      Ready    control-plane   8d    v1.34.3+k3s1   10.0.2.2         <none>        Ubuntu 22.04.5 LTS   5.15.0-168-generic   containerd://2.1.5-k3s1
cisco@ubuntu17:~$ kubectl get pods -o wide
NAME                                     READY   STATUS    RESTARTS   AGE    IP            NODE          NOMINATED NODE   READINESS GATES
cisco-virtual-kubelet-6bfd44b5c5-jpbmd   1/1     Running   0          2m9s   10.0.0.161    ubuntu17      <none>           <none>
iox-xe-hello-app-pod                     1/1     Running   0          108s   10.100.0.15   cat8kv-node   <none>           <none>
cisco@ubuntu17:~$

@joshhalley joshhalley merged commit e76b20d into develop Feb 7, 2026
@joshhalley joshhalley deleted the pr/johalley/node_update branch February 7, 2026 17:53
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.

3 participants