Skip to content
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/srsim-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
test-suite:
- "01*.robot"
- "03*.robot"
- "04*.robot"
- "05*.robot"
- "07*.robot"
- "08*.robot"
Expand Down Expand Up @@ -72,7 +73,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}

- name: Pull and re-tag srsim image
run: docker pull ghcr.io/srl-labs/containerlab/nokia_srsim:25.7.R1 && docker tag ghcr.io/srl-labs/containerlab/nokia_srsim:25.7.R1 registry.srlinux.dev/pub/nokia_srsim:25.7.R1
run: docker pull ghcr.io/srl-labs/containerlab/nokia_srsim:25.10.R1 && docker tag ghcr.io/srl-labs/containerlab/nokia_srsim:25.10.R1 registry.srlinux.dev/pub/nokia_srsim:25.10.R1

# - name: setup tmate session
# uses: mxschmitt/action-tmate@v3
Expand Down
65 changes: 32 additions & 33 deletions core/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,30 +90,14 @@ func (c *CLab) generateAnsibleInventory(w io.Writer) error {
}

for _, n := range c.Nodes {
kind, props := c.getAnsibleKindAndProps(n.Config())
inv.Kinds[kind] = props

ansibleNode := &AnsibleInventoryNode{
NodeConfig: n.Config(),
}

// add AnsibleKindProps to the inventory struct
// the ansibleKindProps is passed as a ref and is populated
// down below
ansibleKindProps := &AnsibleKindProps{}
inv.Kinds[n.Config().Kind] = ansibleKindProps

// add username and password to kind properties
// assumption is that all nodes of the same kind have the same credentials
nodeRegEntry := c.Reg.Kind(n.Config().Kind)
if nodeRegEntry != nil {
ansibleKindProps.Username = nodeRegEntry.GetCredentials().GetUsername()
ansibleKindProps.Password = nodeRegEntry.GetCredentials().GetPassword()
}

// add network_os to the node
ansibleKindProps.setNetworkOS(n.Config().Kind)
// add ansible_connection to the node
ansibleKindProps.setAnsibleConnection(n.Config().Kind)

inv.Nodes[n.Config().Kind] = append(inv.Nodes[n.Config().Kind], ansibleNode)
inv.Nodes[kind] = append(inv.Nodes[kind], ansibleNode)

if n.Config().Labels["ansible-group"] != "" {
inv.Groups[n.Config().Labels["ansible-group"]] =
Expand Down Expand Up @@ -148,24 +132,39 @@ func (c *CLab) generateAnsibleInventory(w io.Writer) error {
return err
}

// setNetworkOS sets the network_os variable for the kind.
func (n *AnsibleKindProps) setNetworkOS(kind string) {
switch kind {
case "nokia_srlinux", "srl":
n.NetworkOS = "nokia.srlinux.srlinux"
case "nokia_sros", "vr-sros", "nokia_srsim":
n.NetworkOS = "nokia.sros.md"
// Determine Ansible kind and properties for containerlab node
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

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

The function comment should document the special handling of classic mode SROS nodes where the ansible group name is modified from the original kind. For example: "Determine Ansible kind and properties for containerlab node. For SROS nodes with CLAB_SROS_CONFIG_MODE=classic, returns 'nokia_srsim_classic' as the kind to enable proper Ansible network_os grouping."

Suggested change
// Determine Ansible kind and properties for containerlab node
// Determine Ansible kind and properties for containerlab node.
// For SROS nodes with CLAB_SROS_CONFIG_MODE=classic, returns "nokia_srsim_classic" as the kind
// to enable proper Ansible network_os grouping. This ensures that classic mode SROS nodes are
// grouped separately in the Ansible inventory and receive the correct network_os and connection settings.

Copilot uses AI. Check for mistakes.
func (c *CLab) getAnsibleKindAndProps(cfg *clabtypes.NodeConfig) (string, *AnsibleKindProps) {
ansibleGroup := cfg.Kind
ansibleProps := &AnsibleKindProps{}

// Set `ansible_user` and `ansible_password`
// Assumption: All nodes of the same kind share same credentials
nodeRegEntry := c.Reg.Kind(ansibleGroup)
if nodeRegEntry != nil {
ansibleProps.Username = nodeRegEntry.GetCredentials().GetUsername()
ansibleProps.Password = nodeRegEntry.GetCredentials().GetPassword()
}

// Generally we use the containerlab kind for grouping in Ansible Inventory.
// Special case: For SROS we differentiate between classic and model-driven.
if cfg.Env["CLAB_SROS_CONFIG_MODE"] == "classic" {
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

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

The string comparison should use strings.EqualFold or convert to lowercase for case-insensitive comparison, similar to how it's checked in nodes/sros/sros.go:459 with strings.ToLower(). This ensures consistent behavior when users set the environment variable in different cases (e.g., "Classic", "CLASSIC", "classic").

Suggested change
if cfg.Env["CLAB_SROS_CONFIG_MODE"] == "classic" {
if strings.EqualFold(cfg.Env["CLAB_SROS_CONFIG_MODE"], "classic") {

Copilot uses AI. Check for mistakes.
ansibleGroup = "nokia_srsim_classic"
}
}

// setAnsibleConnection sets the ansible_connection variable for the kind.
func (n *AnsibleKindProps) setAnsibleConnection(kind string) {
switch kind {
// Set `ansible_network_os` and `ansible_connection`
switch ansibleGroup {
case "nokia_srlinux", "srl":
n.AnsibleConn = "ansible.netcommon.httpapi"
ansibleProps.NetworkOS = "nokia.srlinux.srlinux"
ansibleProps.AnsibleConn = "ansible.netcommon.httpapi"
case "nokia_sros", "vr-sros", "nokia_srsim":
n.AnsibleConn = "ansible.netcommon.network_cli"
ansibleProps.NetworkOS = "nokia.sros.md"
ansibleProps.AnsibleConn = "ansible.netcommon.network_cli"
case "nokia_srsim_classic":
ansibleProps.NetworkOS = "nokia.sros.classic"
ansibleProps.AnsibleConn = "ansible.netcommon.network_cli"
}

return ansibleGroup, ansibleProps
}

// Nornir Simple Inventory
Expand Down
22 changes: 19 additions & 3 deletions docs/manual/kinds/sros.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ Data interfaces need to be configured with IP addressing manually using the SR O

## SR-SIM variants

The SR-SIM can emulate different hardware platforms as explained in the [SR-SIM Installation, deployment and setup guide](https://documentation.nokia.com/sr/25-7/7750-sr/titles/sr-sim-installation-setup.html). These variants can be set using the `type` directive in the clab topology file, or by overriding the different available environment variables such as the ones for the chassis (`NOKIA_SROS_CHASSIS`) or card (`NOKIA_SROS_CARD`).
The SR-SIM can emulate different hardware platforms as explained in the [SR-SIM Installation, deployment and setup guide](https://documentation.nokia.com/sr/25-10/7750-sr/titles/sr-sim-installation-setup.html). These variants can be set using the `type` directive in the clab topology file, or by overriding the different available environment variables such as the ones for the chassis (`NOKIA_SROS_CHASSIS`) or card (`NOKIA_SROS_CARD`).

Users can then use environment variables to change the default behavior of a given container. If there is a conflict between the `type` field in the topology file and an environment variable in the topology file, the environment variable will take precedence.

Expand Down Expand Up @@ -246,7 +246,7 @@ topology:
When the emulated platform is chassis-based, like SR-7, SR-14s, etc., the SR-SIM node must be defined in a distributed mode in the topology file.

A distributed SR-SIM node consists of two or more containers with a specific role: CPM or IOM. A node can boot in either mode depending on the settings of the `NOKIA_SROS_SLOT` environment variable and the SR-SIM node type.
There are several other variables that will modify the default settings for a simulated chassis (e.g. SFM, XIOM, MDA, etc.), so please check the [SR-SIM Installation guide](https://documentation.nokia.com/sr/25-7/7750-sr/titles/sr-sim-installation-setup.html) for a full list of options.
There are several other variables that will modify the default settings for a simulated chassis (e.g. SFM, XIOM, MDA, etc.), so please check the [SR-SIM Installation guide](https://documentation.nokia.com/sr/25-10/7750-sr/titles/sr-sim-installation-setup.html) for a full list of options.

Containerlab provides two ways to define the distributed variant:

Expand Down Expand Up @@ -656,6 +656,22 @@ configure {
}
```

/// details | Start SR-OS with Classic Management
type: tip

To start `-{{ kind_code_name }}-` nodes in Classic CLI mode, you can use the environment variable `CLAB_SROS_CONFIG_MODE`. When set to `classic` or `mixed`, containerlab will switch the node default CLI and update the generated Ansible inventory accordingly during PostDeploy phase. Note that if you provide a partial configuration, you will have to use the Classic-CLI syntax. To understand the differences between `classic`, `mixed` and `model-driven` modes see the [system management guide](https://documentation.nokia.com/sr/25-10/7x50-shared/system-management/model-driven-management-interfaces.html).

```yaml hl_lines="6-7"
topology:
nodes:
sr-sim1:
kind: nokia_srsim
startup-config: myconfig.partial.txt
env:
CLAB_SROS_CONFIG_MODE: classic
```
///

##### Remote partial files

It is possible to provide a partial config file that is located on a remote HTTP(S) server. This can be done by providing a URL to the file. The URL must start with `http://` or `https://` and must point to a file that is accessible from the containerlab host.
Expand Down Expand Up @@ -718,7 +734,7 @@ Next, it will filter out public keys that are not of RSA/ECDSA type. The remaini

## Packet Capture

Currently, a packet capture on the veth interfaces of the `-{{ kind_display_name }}-` will only display traffic at the ingress direction[^10]. In order to capture traffic bidirectionally, a user needs to create a [mirror service](https://documentation.nokia.com/sr/25-7/7750-sr/books/oam-diagnostics/mirror-services.html) in the SR OS configuration. A simple example topology using [bridges in container namespace](bridge.md#bridges-in-container-namespace) and mirror configuration is provided below for convenience.
Currently, a packet capture on the veth interfaces of the `-{{ kind_display_name }}-` will only display traffic at the ingress direction[^10]. In order to capture traffic bidirectionally, a user needs to create a [mirror service](https://documentation.nokia.com/sr/25-10/7750-sr/books/oam-diagnostics/mirror-services.html) in the SR OS configuration. A simple example topology using [bridges in container namespace](bridge.md#bridges-in-container-namespace) and mirror configuration is provided below for convenience.

/// tab | Topology with mirror service

Expand Down
5 changes: 1 addition & 4 deletions nodes/sros/power.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,7 @@ func (n *sros) generatePowerConfig() string {

cfg := srosPowerConfig[nodeType]

shelves := 1
if s := cfg.Shelves; s != 0 {
shelves = s
}
shelves := max(cfg.Shelves, 1)

modules := 0
switch m := cfg.Modules.(type) {
Expand Down
Loading
Loading