- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-25-2021 02:14 AM
Hello everyone,
is it possible to display only devices from a device group when configuring a service? Normally, when configuring a service, a list of all devices in NSO are shown when entering a "?" after the device-leaf in the CLI. But I would like to only see devices, which belong to a certain device group. Is that somehow possible? I don't want to configure all devices in that device group at once, the user just should be able to see only the devices from that device group as an available option. That would be very helpful if that would be possible, because if there are several hundred devices or even more in NSO, showing the available devices while configuring the service would be very confusing. Especially if not all devices are suited for that service.
To be more specific: I am currently developing a DMVPN-Service, and I have a device-group called 'Hubs', which contains all the DMVPN-Hub-Routers. And when I configure the service, I only want to see these devices from that device group as an available option to choose from.
And if this is possible, what are the changes I have to do to my YANG-Model and my XML-Template?
Thanks a lot in advance,
Robin
Solved! Go to Solution.
- Labels:
-
Developer
-
Other NSO Topics
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-25-2021 08:04 AM
While I don't see anything in the Yang RFC specifically forbidding the above expression, the ncsc compiler treats this as an error - you cannot have literals in a leafref path expression. So, the use of the literal key 'Hubs' would be an error.
If you really need this, you can have another leaf for the name of the device-group. So, something like
leaf group { type leafref { path "/ncs:devices/ncs:device-group/ncs:name"; } default "Hubs"; } leaf hub { type leafref { path "/ncs:devices/ncs:device-group[ncs:name=current()/../group]/ncs:device-name"; } }
This way, you can get completions from the 'Hubs' device-group by default. You can also use "tailf:hidden full" in the "group" leaf above if you don't want to take it as a service input param.
The other thing is that, a device group can contain other device groups - meaning that referring to /devices/device-group/device-name will not work if you have other device-groups in your 'Hubs' device-group. I don't know if that is the case. If not, the above snippet will be fine. But if you do have nested device-groups, you need to refer to the 'member' leaf-list which contains a flat list of all the devices in the group. The problem is that 'member' is a config-false leaf-list, serviced by an internal callpoint. So, you cannot use that as a regular leafref path, as shown above. I came up with this:
leaf group { type leafref { path "/ncs:devices/ncs:device-group/ncs:name"; } default "Hubs"; } leaf hub { type leafref { path "/ncs:devices/ncs:device/ncs:name"; } tailf:non-strict-leafref { path "/ncs:devices/ncs:device-group[ncs:name=current()/../group]/ncs:member"; } }
Here, the actual type of the leaf is a reference to all devices - /devices/device/name. But the non-strict-leafref (which is a tailf/cisco specific extension) will make the CLI completion work only with those values from that specific device-group.
/Ram
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-25-2021 05:31 AM
So instead of
path “/ncs:devices/ncs:device/ncs:name“ ;
use
leaf hub {
type leaftef {
path “/ncs :devices/ncs :device-group[name=’Hubs’]/ncs :device-name“ ;
}
In the template beware that the deref function applied to that hub leaf takes you to the group entry rather than the device name under /devices/device
I’ve not tried it but an xpath like deref(deref/hub))/../config should let you read values from the device config, that is because there is a leafref from the device-name in the group to the real device name under devices/device
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-25-2021 07:17 AM
Thanks for your answer, however I encounter the following error message when I try to change the path in the yang-model according to your proposed solution:
"error: bad argument value “/ncs :devices/ncs :device-group[name=’Hubs’]/ncs :device-name“ should be of type path-arg"
Do you know what that means? Because I couldn't make any sense of what is written regarding path-arg in the RFC 6020, where YANG is defined.
Best Regards,
Robin
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-25-2021 08:04 AM
While I don't see anything in the Yang RFC specifically forbidding the above expression, the ncsc compiler treats this as an error - you cannot have literals in a leafref path expression. So, the use of the literal key 'Hubs' would be an error.
If you really need this, you can have another leaf for the name of the device-group. So, something like
leaf group { type leafref { path "/ncs:devices/ncs:device-group/ncs:name"; } default "Hubs"; } leaf hub { type leafref { path "/ncs:devices/ncs:device-group[ncs:name=current()/../group]/ncs:device-name"; } }
This way, you can get completions from the 'Hubs' device-group by default. You can also use "tailf:hidden full" in the "group" leaf above if you don't want to take it as a service input param.
The other thing is that, a device group can contain other device groups - meaning that referring to /devices/device-group/device-name will not work if you have other device-groups in your 'Hubs' device-group. I don't know if that is the case. If not, the above snippet will be fine. But if you do have nested device-groups, you need to refer to the 'member' leaf-list which contains a flat list of all the devices in the group. The problem is that 'member' is a config-false leaf-list, serviced by an internal callpoint. So, you cannot use that as a regular leafref path, as shown above. I came up with this:
leaf group { type leafref { path "/ncs:devices/ncs:device-group/ncs:name"; } default "Hubs"; } leaf hub { type leafref { path "/ncs:devices/ncs:device/ncs:name"; } tailf:non-strict-leafref { path "/ncs:devices/ncs:device-group[ncs:name=current()/../group]/ncs:member"; } }
Here, the actual type of the leaf is a reference to all devices - /devices/device/name. But the non-strict-leafref (which is a tailf/cisco specific extension) will make the CLI completion work only with those values from that specific device-group.
/Ram
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-25-2021 12:34 PM
Ram,
I answered this too fast without coding it and checking...
thanks for the great reply, if you go into the syntax definitions of the RFC, you will see that there is no way to express an xpath with literals, but its hidden in the rules of the formal grammar definition.
The non-strict-leafref example is IMO also very usefiul.
cheers
Stefano
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-26-2021 12:54 AM
Thank you very much, the first part was enough to do the trick for me, since I don't have nested device-groups. It now works like how I imagined it.
Best Regards,
Robin

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
09-10-2024 01:00 AM
Hi Ram,
I'm attempting something somewhat similar but get the error "A non-strict leafref cannot have the type set to 'leafref'".
My structure is something like:
list vrf {
list subnet {
leaf group {
tailf:info "Switchgroup";
mandatory true;
type leafref {
path "/ncs:devices/ncs:device-group/ncs:name";
}
must ". != contains(current(),'-')";
}
list accessports {
key "device port";
leaf device {
type leafref {
path "/ncs:devices/ncs:device/ncs:name";
}
tailf:non-strict-leafref {
path "/ncs:devices/ncs:device-group[ncs:name=current()/../../group]/ncs:member";
}
}
leaf port {
type leafref {
path "/ncs:devices/ncs:device[ncs:name=current()/../device]/ncs:config/ios:interface/ios:GigabitEthernet/ios:name";
}
must "contains(deref(current())/../ios:description,'Available'))" {
tailf:dependency "/ncs:devices/ncs:device/ncs:config/ios:interface/ios:GigabitEthernet/ios:description";
}
}
}
}
}
Any ideas why this is not working for me (I'm running this in NSO version 6.3)?
- Johnny
