09-17-2024 12:23 PM
I can manually create instances of this service and create instances via the API. But I can't get the list of services to show up with http://192.168.2.100:8080/restconf/data/tailf-ncs:services/service. It returns a "204 no content". So the API call is right, it's looking at services under tailf-ncs:services, but there isn't anything there.
So, I think the service model isn't putting instances under tailf-ncs:services.
What I'm trying to do is create instances with the API (which works with this API call:
module l2vpn {
namespace "http://com/example/l2vpn";
prefix l2vpn;
import ietf-inet-types {
prefix inet;
}
import tailf-common {
prefix tailf;
}
import tailf-ncs {
prefix ncs;
}
description
"This service creates L2VPNs across Cisco IOSXR and IOS for the NSO Basic Service Model Lab";
revision 2021-02-11 {
description
"V1 all datapoints modeled";
}
augment /ncs:services {
list l2vpn {
key name;
uses ncs:service-data;
ncs:servicepoint "l2vpn";
// set the service name.
leaf name {
tailf:info "Service instance name / Customer name";
mandatory true;
type string;
}
// set the pseudo wire ID.
leaf pw-id {
tailf:info "Unique pseudowire or virtual circuit number";
mandatory true;
type uint32 {
range "1..4294967295";
}
}
// set the ios device name.
leaf ios_device {
tailf:info "Select the Cisco IOS device";
mandatory true;
type leafref {
path "/ncs:devices/ncs:device/ncs:name";
}
}
// set the ios device port
leaf ios_port {
tailf:info "Set the Cisco IOS device port number in form X/X";
mandatory true;
type string;
}
// set the xr device name. }
leaf xr_device {
tailf:info "Select the Cisco IOSXR dervice";
mandatory true;
type leafref {
path "/ncs:devices/ncs:device/ncs:name";
}
}
// set the xr device port
leaf xr_port {
tailf:info "Set the Cisoc IOSXR dervice port number in the form X/X/X/X";
mandatory true;
type string;
}
// set the ios device xconnect IP.
leaf ios_xconnect_ip {
tailf:info "Set the neighbor IP for the IOS device (the IOSXR device loopback)";
mandatory true;
type inet:ipv4-address;
}
// set the ios device xconnect encapsulation.
leaf ios_xconnect_encap {
tailf:info "Select the encapsulation for the IOS device";
mandatory true;
type enumeration {
enum "l2tpv3";
enum "mpls";
}
}
// set the ios device port description
leaf ios_description {
tailf:info "Set the description for the IOS device side port";
mandatory true;
type string;
}
// set the xr device xconnect group name
leaf xr_group {
tailf:info "Set the xconnect group name for the IOSXR dervice";
mandatory true;
type string;
}
// set the xr device xconnect p2p name
leaf xr_p2p {
tailf:info "Set the IOSXR p2p group name";
mandatory true;
type string;
}
// set the ios device xconnect neighbor IP.
leaf xr_xconnect_ip {
tailf:info "Set the neighbor IP for the IOSXR device (the IOS device loopback) ";
mandatory true;
type inet:ipv4-address;
}
// set the xr device port description name
leaf xr_description {
tailf:info "Set the description for the IOSXR side port";
mandatory true;
type string;
}
}
}
}
<config-template xmlns="http://tail-f.com/ns/config/1.0"
servicepoint="l2vpn">
<devices xmlns="http://tail-f.com/ns/ncs">
<!-- This section is for the ios device -->
<device>
<name>{/ios_device}</name>
<config>
<interface xmlns="urn:ios">
<GigabitEthernet>
<name>{/ios_port}</name>
<xconnect>
<address>{/ios_xconnect_ip}</address>
<vcid>{/pw-id}</vcid>
<encapsulation>{/ios_xconnect_encap}</encapsulation>
</xconnect>
<description>{/ios_description}</description>
</GigabitEthernet>
</interface>
</config>
</device>
<!-- This section is for the xr device -->
<device>
<name>{/xr_device}</name>
<config>
<l2vpn xmlns="http://tail-f.com/ned/cisco-ios-xr">
<xconnect>
<group>
<name>{/xr_group}</name>
<p2p>
<name>{/xr_p2p}</name>
<interface>
<name>GigabitEthernet{/xr_port}</name>
</interface>
<neighbor>
<address>{/xr_xconnect_ip}</address>
<pw-id>{/pw-id}</pw-id>
</neighbor>
</p2p>
</group>
</xconnect>
</l2vpn>
<interface xmlns="http://tail-f.com/ned/cisco-ios-xr">
<GigabitEthernet>
<id>{/xr_port}</id>
<description>{/xr_description}</description>
<l2transport/>
</GigabitEthernet>
</interface>
</config>
</device>
</devices>
</config-template>
Solved! Go to Solution.
09-18-2024 09:59 AM
OK, I think I have it figured out...
First thing, make sure you do a packages reload on your service. I had changed the service to use tailf-ncs:services, compiled it then forgot to reload the package.
Then I had to experiment with the RESTCONF API to get my desired result. Here are the API calls to get a list of services, add a service (JSON), add a service (XML) and delete a service instance:
Get a list of services instances
curl --location 'http://192.168.2.100:8080/restconf/data/tailf-ncs:services' \
--header 'application: yang-data+xml' \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Accept: application/yang-data+xml' \
--data ''
Add a service instance using JSON
curl --location 'http://192.168.2.100:8080/restconf/data/tailf-ncs:services/' \
--header 'Content-Type: application/yang-data+json' \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--data '{
"l2vpn:l2vpn": [
{
"name": "APIdeployed-xml",
"pw-id": 121,
"ios_device": "ios0",
"ios_port": "0/9",
"xr_device": "xr0",
"xr_port": "0/0/0/9",
"ios_xconnect_ip": "10.0.0.10",
"ios_xconnect_encap": "mpls",
"ios_description": "test",
"xr_group": "acme",
"xr_p2p": "acme",
"xr_xconnect_ip": "10.0.0.11",
"xr_description": "test"
}
]
}
'
Add a service instance using XML
curl --location 'http://192.168.2.100:8080/restconf/data/tailf-ncs:services/' \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Content-Type: application/yang-data+xml' \
--data ' <l2vpn xmlns="http://com/example/l2vpn">
<name>APIdeployed-json</name>
<pw-id>125</pw-id>
<ios_device>ios0</ios_device>
<ios_port>0/9</ios_port>
<xr_device>xr0</xr_device>
<xr_port>0/0/0/9</xr_port>
<ios_xconnect_ip>10.0.0.10</ios_xconnect_ip>
<ios_xconnect_encap>mpls</ios_xconnect_encap>
<ios_description>test</ios_description>
<xr_group>acme</xr_group>
<xr_p2p>acme</xr_p2p>
<xr_xconnect_ip>10.0.0.11</xr_xconnect_ip>
<xr_description>test</xr_description>
</l2vpn>
'
Delete a service instance (must specify the exact name)
curl --location --request DELETE 'http://192.168.2.100:8080/restconf/data/tailf-ncs:services/l2vpn:l2vpn=APIdeployed-xml' \
--header 'Accept: application/yang-data+xml' \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Content-Type: application/yang-data+xml' \
--data '
'
09-17-2024 10:53 PM
Hello,
I think you should change the url to http://192.168.2.100:8080/restconf/data/tailf-ncs:services/l2vpn:l2vpn
If you don't know the exact path, you can create an instance using RESTCONF or CLI then in CLI get the restconf path
show running services l2vpn | display restconf
09-18-2024 09:59 AM
OK, I think I have it figured out...
First thing, make sure you do a packages reload on your service. I had changed the service to use tailf-ncs:services, compiled it then forgot to reload the package.
Then I had to experiment with the RESTCONF API to get my desired result. Here are the API calls to get a list of services, add a service (JSON), add a service (XML) and delete a service instance:
Get a list of services instances
curl --location 'http://192.168.2.100:8080/restconf/data/tailf-ncs:services' \
--header 'application: yang-data+xml' \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Accept: application/yang-data+xml' \
--data ''
Add a service instance using JSON
curl --location 'http://192.168.2.100:8080/restconf/data/tailf-ncs:services/' \
--header 'Content-Type: application/yang-data+json' \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--data '{
"l2vpn:l2vpn": [
{
"name": "APIdeployed-xml",
"pw-id": 121,
"ios_device": "ios0",
"ios_port": "0/9",
"xr_device": "xr0",
"xr_port": "0/0/0/9",
"ios_xconnect_ip": "10.0.0.10",
"ios_xconnect_encap": "mpls",
"ios_description": "test",
"xr_group": "acme",
"xr_p2p": "acme",
"xr_xconnect_ip": "10.0.0.11",
"xr_description": "test"
}
]
}
'
Add a service instance using XML
curl --location 'http://192.168.2.100:8080/restconf/data/tailf-ncs:services/' \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Content-Type: application/yang-data+xml' \
--data ' <l2vpn xmlns="http://com/example/l2vpn">
<name>APIdeployed-json</name>
<pw-id>125</pw-id>
<ios_device>ios0</ios_device>
<ios_port>0/9</ios_port>
<xr_device>xr0</xr_device>
<xr_port>0/0/0/9</xr_port>
<ios_xconnect_ip>10.0.0.10</ios_xconnect_ip>
<ios_xconnect_encap>mpls</ios_xconnect_encap>
<ios_description>test</ios_description>
<xr_group>acme</xr_group>
<xr_p2p>acme</xr_p2p>
<xr_xconnect_ip>10.0.0.11</xr_xconnect_ip>
<xr_description>test</xr_description>
</l2vpn>
'
Delete a service instance (must specify the exact name)
curl --location --request DELETE 'http://192.168.2.100:8080/restconf/data/tailf-ncs:services/l2vpn:l2vpn=APIdeployed-xml' \
--header 'Accept: application/yang-data+xml' \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Content-Type: application/yang-data+xml' \
--data '
'
09-19-2024 02:54 AM
I have found this package to be useful to see the REST paths https://gitlab.com/nso-developer/rest-api-explorer consider installing it in your developer environment. One important note, only works with Chrome. I have tested in 6.2.5 and works.
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