11-10-2025 09:47 AM
Hi all,
I hope someone can show me the obvious mistake i'm making.
I am following this https://developer.cisco.com/docs/nso-guides-5.7/creating-a-service/#creating-a-service to create a basic DNS service.
Whenever i issue a "commit dry-run" i get this error
admin@ncs(config)# dns-config test dns-server 1.1.1.1 admin@ncs(config-dns-config-test)# commit dry-run Aborted: Python cb_create error. 'Container' object has no attribute 'sys'
my python code is very similar to the example
@Service.create
def cb_create(self, tctx, root, service, proplist):
self.log.info('Service create(service=', service._path, ')')
dns_ip = service.dns_server
router0_device = root.devices.device['router0']
router0_config = router0_device.config
dns_server_list = router0_config.sys.dns.server
if dns_ip not in dns_server_list:
dns_server_list.create(dns_ip)my yang file is as follows - the same as the example
module dns-config {
namespace "http://example.com/dns-config";
prefix dns-config;
import ietf-inet-types {
prefix inet;
}
import tailf-common {
prefix tailf;
}
import tailf-ncs {
prefix ncs;
}
description
"Bla bla...";
revision 2016-01-01 {
description
"Initial revision.";
}
list dns-config {
description "This is an RFS skeleton service";
key name;
leaf name {
tailf:info "Unique service id";
tailf:cli-allow-range;
type string;
}
uses ncs:service-data;
ncs:servicepoint dns-config-servicepoint;
// may replace this with other ways of refering to the devices.
leaf-list device {
type leafref {
path "/ncs:devices/ncs:device/ncs:name";
}
}
// replace with your own stuff here
leaf dns-server {
type inet:ipv4-address;
}
}
}my router package is as follows
~/ncs-6.2/nso-instance/packages/ ls -la total 0 drwxr-xr-x@ 4 rich staff 128 10 Nov 15:59 . drwxr-xr-x@ 13 rich staff 416 10 Nov 16:16 .. lrwxr-xr-x@ 1 rich staff 51 7 Nov 16:03 cisco-ios-cli-3.8 -> /Users/rich/ncs-6.2/packages/neds/cisco-ios-cli-3.8 drwxr-xr-x@ 9 rich staff 288 10 Nov 16:17 dns-config
Thanks
Rich
Solved! Go to Solution.
11-11-2025 04:38 AM
Hi, I haven't had the chance to look closely at your issue. But if I'm not mistaken, this line refers to the config on the Device from the NED, where you most probably don't have a sys container. You can try to configure manually a device from the cli using the NED (not from your service)
router0_config.sys.dns.server
if you want to refer to the structure of your service, you should use the `service` parameter from the `cb_create` function. Then you commit that config. On your yang file I also don't see a sys container, unless you are using the top yang model from the example.
def cb_create(self, tctx, root, service, proplist)
here you can see an example I created for a workshop I delivered on the Python API of NSO https://github.com/jillesca/DEVWKS-3551/blob/main/answers/package_router/router.py#L18 you can run this workshop if you want. Read main the README to find the instructions since the workshop is broken and is up to you to fix it (that was the goal of the workshop. The answers are there, in fact the link I sent you is one of them).
Here are some general recommendations that I think can be useful for your use case.
11-11-2025 06:03 AM
@richbotham sure i am mostly guessing here, the python part i know, my nso is little shaky, but we have @Jesus Illescas here who is on of the best in the world with nso... so we are in good hands and he will tell you if i can talking pony here.
This new errors, is happening due to where you are accessing the configuration path as python interprets the hyphens as subtraction operators. So to fix this i 'think' yuo need to use the square brackets (like a dictionary), when using name which have special chars, such as hyphens... this is a little bit of a guess, but see if this fixed the error
@Service.create
def cb_create(self, tctx, root, service, proplist):
self.log.info('Service create(service=', service._path, ')')
dns_ip = service.dns_server
router0_device = root.devices.device['router0']
dns_list = router0_device.config.ip['name-server']['name-server-list']
if dns_ip not in dns_list:
dns_list.create(dns_ip)
Fingers crossed here!
11-10-2025 01:16 PM
Check if the NED has the sys.dns.server path, i think it doesn’t and this is the issue.
11-11-2025 04:38 AM
Hi, I haven't had the chance to look closely at your issue. But if I'm not mistaken, this line refers to the config on the Device from the NED, where you most probably don't have a sys container. You can try to configure manually a device from the cli using the NED (not from your service)
router0_config.sys.dns.server
if you want to refer to the structure of your service, you should use the `service` parameter from the `cb_create` function. Then you commit that config. On your yang file I also don't see a sys container, unless you are using the top yang model from the example.
def cb_create(self, tctx, root, service, proplist)
here you can see an example I created for a workshop I delivered on the Python API of NSO https://github.com/jillesca/DEVWKS-3551/blob/main/answers/package_router/router.py#L18 you can run this workshop if you want. Read main the README to find the instructions since the workshop is broken and is up to you to fix it (that was the goal of the workshop. The answers are there, in fact the link I sent you is one of them).
Here are some general recommendations that I think can be useful for your use case.
11-11-2025 07:14 AM
Hi @jesusillescas Many many thanks for the link - more learning to do
11-11-2025 05:54 AM
Many thanks for taking the time to reply - appreciate it.
So i looked at ~/ncs6.2/nso-instance/packages/neds/cisco-ios-cli-3.8/src/yang/tailf-ned-cisco-ios.yang
admin@ncs# show devices ned-ids
ID NAME REVISION NAMESPACE
-------------------------------------------------------------------------
lsa-netconf
netconf
snmp
cisco-ios-cli-3.8 tailf-ned-cisco-ios 2015-03-16 urn:ios
tailf-ned-cisco-ios-stats - urn:ios-stats
I found that by looking at the URL in NSO under 'edit config' i see this
ncs:devices/device{router0}/config/ios:ip/name-server/name-server-listWhich corresponds with this in the NED yang file
// ip-name-server-grouping
grouping ip-name-server-grouping {
list name-server-list {
tailf:cli-drop-node-name;
tailf:cli-suppress-mode;
tailf:cli-delete-when-empty;
max-elements 6;
key address;
leaf address {
type union {
type inet:ipv4-address {
tailf:info "A.B.C.D;;Domain server IP address (maximum of 6)";
}
type inet:ipv6-address {
tailf:info "X:X:X:X::X;;Domain server IPv6 address (maximum of 6)";
}
}
}
}
}
So I amended the code as follows
@Service.create
def cb_create(self, tctx, root, service, proplist):
self.log.info('Service create(service=', service._path, ')')
dns_ip = service.dns_server
router0_device = root.devices.device['router0']
router0_config = router0_device.config
dns_server_list = router0_config.ip.name-server.name-server-list.address
if dns_ip not in dns_server_list:
dns_server_list.create(dns_ip)
Then i reload the package which is successful
Then i apply the config, however when I commit dry-run i get this
admin@ncs(config)# dns-config router0 dns-server 1.1.1.1
admin@ncs(config-dns-config-router0)# commit dry-run
Aborted: Python cb_create error. 'Container' object has no attribute 'name'
admin@ncs(config-dns-config-router0)#
11-11-2025 06:03 AM
@richbotham sure i am mostly guessing here, the python part i know, my nso is little shaky, but we have @Jesus Illescas here who is on of the best in the world with nso... so we are in good hands and he will tell you if i can talking pony here.
This new errors, is happening due to where you are accessing the configuration path as python interprets the hyphens as subtraction operators. So to fix this i 'think' yuo need to use the square brackets (like a dictionary), when using name which have special chars, such as hyphens... this is a little bit of a guess, but see if this fixed the error
@Service.create
def cb_create(self, tctx, root, service, proplist):
self.log.info('Service create(service=', service._path, ')')
dns_ip = service.dns_server
router0_device = root.devices.device['router0']
dns_list = router0_device.config.ip['name-server']['name-server-list']
if dns_ip not in dns_list:
dns_list.create(dns_ip)
Fingers crossed here!
11-11-2025 06:08 AM - edited 11-11-2025 06:10 AM
Hey @bigevilbeard
Thanks buddy - that did it - i should have seen that coming in the python code ( DOH) - makes sense now
admin@ncs(config-dns-config-router0)# commit dry-run
cli {
local-node {
data devices {
device router0 {
config {
ip {
name-server {
+ name-server-list 1.1.1.1 {
+ }
}
}
}
}
}
+dns-config router0 {
+ dns-server 1.1.1.1;
+}
}
}
admin@ncs(config-dns-config-router0)# router0# show running-config
<snip>
!
ip name-server 1.1.1.1
11-11-2025 06:52 AM
@richbotham amazing! Lucky guess, you did all the hard work!
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide