cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
242
Views
0
Helpful
3
Replies

Service model instances not showing up as services, tailf-ncs:services

ron.whitt
Level 1
Level 1

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: 

--header 'application: vnd.yang-data+json' \
--header 'Authorization: Basic YWRtaW46YWRtaW4=' \
--header 'Content-Type: application/yang-data+json' \
--data '{
    "l2vpn:l2vpn": [
      {
        "name": "APIdeployed-3",
        "pw-id": 122,
        "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"
      }
    ]
}
'
But the instance never shows up when you try to query the services list.
So, probably something wrong with my service model.  I'll put all the files below:
 NSO version: 6.1
Here is the YANG model
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;   
      }  
    }
  }
}
 
Here is the template file:
<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>

1 Accepted Solution

Accepted Solutions

ron.whitt
Level 1
Level 1

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 '
'

 

View solution in original post

3 Replies 3

Nabsch
Spotlight
Spotlight

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

 

ron.whitt
Level 1
Level 1

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 '
'

 

Jesus Illescas
Cisco Employee
Cisco Employee

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.