cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Announcements
876
Views
0
Helpful
2
Replies
dapryor
Cisco Employee

Best approach to convert this container to a list?

Hey all,

 

per request, I need to change my service to allow for multiple interfaces to be specified.  Currently, I have a container named "interface" where I configure one interface.  I am looking to restructure this container to be a list where the key is the interface type, number, and dot1q tag.  Due to the ifType and if_number being nested within "device type" containers, I don't know of an easy way to use this structure in a list.  I could remove all containers and validate interface type and number within the python code, but I would rather keep as much validation as possible within the YANG.

container interface {
        tailf:cli-add-mode;
	      container iosxr {
          when "/ncs:devices/ncs:device[ncs:name=current()/../../device]/ncs:device-type/ncs:cli/ncs:ned-id='cisco-ios-xr-id:cisco-ios-xr'"{
            tailf:dependency "../../device";
            tailf:dependency "/ncs:devices/ncs:device/ncs:device-type/ncs:cli/ncs:ned-id";
            tailf:dependency "/ncs:devices/ncs:device/ncs:name";
          }
          tailf:cli-drop-node-name;
          tailf:cli-sequence-commands;
          tailf:cli-compact-syntax;
          leaf ifType {
  	        tailf:info "Interface type.";
            mandatory true;
  	        type enumeration {
              enum GigabitEthernet;
  	          enum TenGigabitEthernet;
  	        }
  	      }
          container GigabitEthernet {
            when "current()/../ifType='GigabitEthernet'";
            tailf:cli-drop-node-name;
            leaf ifnumber {
              tailf:info "Gigabit Ethernet Interface Number";
              mandatory true;
              type leafref {
                path "/ncs:devices/ncs:device[ncs:name=current()/../../../../device]"+
                      "/ncs:config/cisco-ios-xr:interface/cisco-ios-xr:GigabitEthernet/"+
                      "cisco-ios-xr:id";
              }
            }
          }
          container TenGigabitEthernet {
            when "current()/../ifType='TenGigabitEthernet'"
            tailf:cli-drop-node-name;
            leaf ifnumber {
              tailf:info "Ten Gigabit Ethernet Interface Number";
              mandatory true;
              type leafref {
                path "/ncs:devices/ncs:device[ncs:name=current()/../../../../device]"+
                      "/ncs:config/cisco-ios-xr:interface/cisco-ios-xr:TenGigE/"+
                      "cisco-ios-xr:id";
              }
            }
          }
        }
  
        container ios {
          when "/ncs:devices/ncs:device[ncs:name=current()/../../device]/ncs:device-type/ncs:cli/ncs:ned-id='ios-id:cisco-ios'"{
            tailf:dependency "../../device";
            tailf:dependency "/ncs:devices/ncs:device/ncs:device-type/ncs:cli/ncs:ned-id";
            tailf:dependency "/ncs:devices/ncs:device/ncs:name";
          }
          tailf:cli-drop-node-name;
          tailf:cli-sequence-commands;
          tailf:cli-compact-syntax;
  	      leaf ifType {
  	        tailf:info "Interface type.";
            mandatory true;
  	        type enumeration {
  	          enum FastEthernet;
              enum GigabitEthernet;
  	          enum TenGigabitEthernet;
  	        }
  	      }
          container FastEthernet {
            when "current()/../ifType='FastEthernet'";
            tailf:cli-drop-node-name;
            leaf ifnumber {
              tailf:info "Fast Ethernet Interface Number";
              mandatory true;
              type leafref {
                path "/ncs:devices/ncs:device[ncs:name=current()/../../../../device]"+
                      "/ncs:config/ios:interface/ios:FastEthernet"+
                      "/ios:name";
              }
            }
          }
          container GigabitEthernet {
            when "current()/../ifType='GigabitEthernet'";
            tailf:cli-drop-node-name;
            leaf ifnumber {
              tailf:info "Gigabit Ethernet Interface Number";
              mandatory true;
              type leafref {
                path "/ncs:devices/ncs:device[ncs:name=current()/../../../../device]"+
                      "/ncs:config/ios:interface/ios:GigabitEthernet"+
                      "/ios:name";
              }
            }
          }
          container TenGigabitEthernet {
            when "current()/../ifType='TenGigabitEthernet' or " +
                  "current()/../ifType='TenGigE'";
            tailf:cli-drop-node-name;
            leaf ifnumber {
              tailf:info "Ten Gigabit Ethernet Interface Number";
              mandatory true;
              type leafref {
                path "/ncs:devices/ncs:device[ncs:name=current()/../../../../device]"+
                      "/ncs:config/ios:interface/ios:TenGigabitEthernet"+
                      "/ios:name";
              }
            }
          }
        }

        container huawei {
          when "/ncs:devices/ncs:device[ncs:name=current()/../../device]/ncs:device-type/ncs:cli/ncs:ned-id='huawei-vrp-id:huawei-vrp'"{
            tailf:dependency "../../device";
            tailf:dependency "/ncs:devices/ncs:device/ncs:device-type/ncs:cli/ncs:ned-id";
            tailf:dependency "/ncs:devices/ncs:device/ncs:name";
          }
          tailf:cli-drop-node-name;
          tailf:cli-sequence-commands;
          tailf:cli-compact-syntax;
  	      leaf ifType {
  	        tailf:info "Interface type.";
            mandatory true;
  	        type enumeration {
              enum GigabitEthernet;
  	          enum TenGigabitEthernet;
  	          enum Eth-Trunk;
  	        }
  	      }
          container GigabitEthernet {
            when "current()/../ifType='GigabitEthernet'";
            tailf:cli-drop-node-name;
            leaf ifnumber {
              tailf:info "Gigabit Ethernet Interface Number";
              mandatory true;
              type leafref {
                path "/ncs:devices/ncs:device[ncs:name=current()/../../../../device]"+
                      "/ncs:config/vrp:interface/vrp:GigabitEthernet"+
                      "/vrp:name";
              }
            }
          }
          container TenGigabitEthernet {
            when "current()/../ifType='TenGigabitEthernet' or " +
                  "current()/../ifType='TenGigE'";
            tailf:cli-drop-node-name;
            leaf ifnumber {
              tailf:info "Ten Gigabit Ethernet Interface Number";
              mandatory true;
              type leafref {
                path "/ncs:devices/ncs:device[ncs:name=current()/../../../../device]"+
                      "/ncs:config/vrp:interface/vrp:TenGigabitEthernet"+
                      "/vrp:name";
              }
            }
          }
          container Eth-Trunk {
            when "current()/../ifType='Eth-Trunk'";
            tailf:cli-drop-node-name;
            leaf ifnumber {
              tailf:info "Eth-Trunk Interface Number";
              mandatory true;
              type leafref {
                path "/ncs:devices/ncs:device[ncs:name=current()/../../../../device]"+
                      "/ncs:config/vrp:interface/vrp:Eth-Trunk"+
                      "/vrp:name";
              }
            }
          }
        }
        uses subinterface_group;
      }
grouping subinterface_group{
leaf if_description {
tailf:info "Interface description";
mandatory false;
type string;
}
leaf tag_dot1q{
tailf:info "VLAN ID.";
mandatory true;
type uint32 { range 1..4094; }
}
leaf ip_address{
tailf:info "IPv4 address for interface.";
mandatory true;
type inet:ipv4-address;
}
leaf mask {
tailf:info "IPv4 subnet mask.";
mandatory true;
type ipv4_mask;
}
}

 

2 REPLIES 2
ramkraja
Cisco Employee

If you want those three leaves to be the keys, there is no way to keep the structure the same. As for validation, maybe you can combine the 'when' expressions and the enum values for 'ifType' into a single must expression, something like:

 

must "(...ned-id='cisco-iosxr' and ifType != 'fastethernet') or (...ned-id='cisco-ios' and ifType != Eth-Trunk) ..." etc.

 

Replicating the leafref will be difficult. Maybe you can use a completion point to supply the valid completions yourself, by reading the configured interfaces and the interface type from CDB? But of course, that does not prevent someone from providing a different value than what is offered as completions - ie., it does not fully mimic the behavior of a leafref. Still, might be an option.

Otherwise, I can't see an easy way to change the model as you want, and still preserve the same semantics/validation.

/Ram

Thanks for the response Ram!  

 

I just had an idea. I could keep the interface container and make three list: iOS, iosxr, Huawei and then add the uses subinterface_grouping inside each of those list.  Finally, I would need to figure out the best way to pull out the different if_number leafs. 

 

Any thoughts on this approach? I'll type it up when I get to my laptop.