cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
749
Views
5
Helpful
3
Replies

Referencing a subset of the devices in a list in a service

rslaski
Spotlight
Spotlight

Guys,

Here's a newbie problem. In my NSO inventory there are a number of switches, let's say ten:

 

rslaski@ncs# show running-config devices device | include hostname
nx:hostname LEAF1111
nx:hostname LEAF1112
nx:hostname LEAF1113
nx:hostname LEAF1114
nx:hostname LEAF1115
nx:hostname LEAF1116
nx:hostname LEAF2221
nx:hostname LEAF2222
nx:hostname LEAF2223
nx:hostname LEAF2224


These devices then needs to be allocated to different DCs, so I have a 'datacenter' dictionary configured, which contains 'dc' list, which in turn contains 'leaf' list:

container datacenters {
    list dc {
	    key dc-id;

        leaf dc-id {
            type uint32 {
            }
        }
        list leaf {
            key name;

            leaf name {
                type leafref {
                    path "/ncs:devices/ncs:device/ncs:name";
                }
            }
        }
    }
}

In my example four devices have been allocated to 'dc 111', and two to 'dc 222':

datacenters
 dc 111
  leaf-node LEAF1111
  !
  leaf-node LEAF1112
  !
  leaf-node LEAF1113
  !
  leaf-node LEAF1114
  !
 !
 dc 222
  leaf-node LEAF2221
  !
  leaf-node LEAF2222

Now inside my RSL namespace module in SRV hierarchy I've created L2 network service that should be applicable to a subset of devices in one particular DC:

container SRV {
	list L2 {
	   uses ncs:service-data;
	   ncs:servicepoint "L2";
		
	   key name;
           leaf name {
               tailf:info "L2 service name";
               type string;
           }
			
	   list dc {
		key dc-id;

		leaf dc-id {
		    type leafref {
			path "/RSL:datacenters/dc/dc-id";
		    }
	        }
		container ports {
		    list access-leaf {
			key node;
                        leaf node {
			    type leafref {
                                path "/ncs:devices/ncs:device/ncs:name";
                            }
			}
		    }
		}
	    }
	}
}

And the sample service configuration follows:

SRV
 L2 test2
  dc 111
   ports
    access-leaf LEAF1111
    access-leaf LEAF1112	

Now I would like to apply constraints so that both:
- YANG model valiates that the device referenced in the service model in a particular dc has been referenced in dc dictionary
- NSO command completion displays only devices relevant to the particular dc

 

Without any constraints, any device can be used for a service:

rslaski@ncs# config t
Entering configuration mode terminal
rslaski@ncs(config)# TMPL L2 test2
syntax error: unknown command
rslaski@ncs(config-L2-test2)# dc 111 
rslaski@ncs(config-dc-111)# ports
rslaski@ncs(config-ports)# access-leaf ?
Possible completions:
  LEAF1111   LEAF1112  LEAF1113  LEAF1114  LEAF1115  LEAF1116  LEAF2221  LEAF2222  LEAF2223  LEAF2224   

In above example I need to add validation stuff that would limit the devices to the devices present only in 'dc 111':

rslaski@ncs(config-ports)# access-leaf ?
Possible completions:
  LEAF1111   LEAF1112  LEAF1113  LEAF1114    

I've tried applying various 'when' and 'tailf:display-when' conditions to "SRV / L2 / dc / ports / access-leaf / node" but I got stuck. Any ideas to help me with that?

 

thanks,
robert

1 Accepted Solution

Accepted Solutions

ramkraja
Cisco Employee
Cisco Employee

Hi,

You can do this with must expressions, but perhaps it is easiest to tweak your leafref paths.

You have "/devices/device/name" as the target for the leaf 'node' - 

        leaf node {
            type leafref {
                path "/ncs:devices/ncs:device/ncs:name";
            }
        }

 This is too broad, as you experienced. You can constrain it to only those devices that are used inside a dc, like so:

        leaf node {
            type leafref {
                path "deref(../../../dc-id)/../leaf/name";
            }
        }

The 'deref' statement "dereferences" the path that it's argument points to. In this case, you are dereferencing the 'dc-id' leaf, which in turn points to /datacenters/dc. Now you have the particular datacenter instance, and from there, you can refer to the "leaf"s in that instance.

 

/Ram

View solution in original post

3 Replies 3

tcragg1
Cisco Employee
Cisco Employee

Not sure if there is a neater way to do this, but you should be able to achieve the effect you are after by setting a "must" constraint under the "node" leaf in the SRV container. The constraint would require the value of the current node to match a deref path that points to the list of leaf names defined within the DC.

 

I think the leaf configuration would end up looking something like the below:

 

leaf node {
	type leafref {
        path "/ncs:devices/ncs:device/ncs:name";
    }
    must "current() = deref(../../../dc-id)/../leaf/name"
}

The deref statement follows the path statement in dc-id, and we then navigate from there to find the list of device names within that dc. If the value of the current node does not match one of these names, YANG validation will fail.

 

If the models are in different modules, you will also need to import the module with the datacenters container into the SRV module. You would also need to prefix "leaf" and "name" in the must constraint with the module name, otherwise you will get a YANG error when you try to make the package.

 

 

ramkraja
Cisco Employee
Cisco Employee

Hi,

You can do this with must expressions, but perhaps it is easiest to tweak your leafref paths.

You have "/devices/device/name" as the target for the leaf 'node' - 

        leaf node {
            type leafref {
                path "/ncs:devices/ncs:device/ncs:name";
            }
        }

 This is too broad, as you experienced. You can constrain it to only those devices that are used inside a dc, like so:

        leaf node {
            type leafref {
                path "deref(../../../dc-id)/../leaf/name";
            }
        }

The 'deref' statement "dereferences" the path that it's argument points to. In this case, you are dereferencing the 'dc-id' leaf, which in turn points to /datacenters/dc. Now you have the particular datacenter instance, and from there, you can refer to the "leaf"s in that instance.

 

/Ram

Yes, this solution works. The other one is also good one, however it's two line code compared to single one ;-)

Thanks a lot!