Search code examples
ietf-netmod-yang

YANG - Modeling non-mandatory containers


Currently I am working with YANG as part of a (legacy) Python project.

I am somewhat stuck at the task of defining a schema, which shall then be used to verify data, organized as a Python dictionary. If it is possible, I would "like" to keep the current structure, since a lot of the codebase is using this data.

An "unaltered" piece of data:

"namespace": {                      # Mandatory
    "management": {                 # Optional
        "interfaces": {             # Mandatory
            "m0": {                 # Optional
                "leaf1": "..."
            }
        }
    },
    "benchmark": {                  # Optional
        "interfaces": {             # Mandatory
            "b0": {                 # Optional
                "leaf1": "...",
                "leaf2": "..."
            },
            "b1": {                 # Optional
                "leaf1": "...",
                "leaf2": "..."
            }
        }
    }
}

My problem is that everything marked as "optional" (in the example) would be modeled as a container but it seems that they cannot be defined as optional (i.e.: mandatory false;) according to RFC6020.

Therefore, I defined a model that is using lists. Meaning some nodes of the Python Dict (management, benchmark, m0, b0, b1) are now list elements and cannot be accessed in the current fashion, e.g.: data['namespace']['management']...

The modified example looks like this:

"namespace": [
    {
        "desc": "management",
        "interfaces": [
            {
                "leaf1": "..."
            }
        ]
    },
    {
        "desc": "benchmark",
        "interfaces": [
            {
                "leaf1": "...",
                "leaf2": "..."
            },
            {
                "leaf1": "...",
                "leaf2": "..."
            }
        ]
    }
]

The describing (snippet from my current) YANG model:

list namespace {
    description "Namespace definitions.";
    key desc;

    leaf desc { type string; }

    uses leaf-definitions;

    list interfaces {
        key leaf1;
        uses leaf-definitions;
    }
}

The verification is successful and the conversion of the data (itself) is not a problem, but it is resulting in a big pile of broken code.

This leads to my question(s):

  1. Am I correct - are containers in YANG always mandatory?
  2. Is there maybe another way to model this scenario? (Without breaking "too much")

I am very thankful for your input, since I am rather new to YANG!


Solution

  • Am I correct - are containers in YANG always mandatory?

    Quite the contrary. They are always optional, unless they contain mandatory nodes (mandatory leaf, a list or leaf-list with min-elements > 0, etc.). In other words, containers inherit this property from their descendants. This of course only applies to non-presence containers. A presence container with mandatory children does not inherit this property, since that would defeat its purpose (presence). You probably missed the definition of a mandatory node in RFC6020:

      A mandatory node is one of:
    
      o  A leaf, choice, or anyxml node with a "mandatory" statement with
          the value "true".
    
      o  A list or leaf-list node with a "min-elements" statement with a
          value greater than zero.
    
      o  A container node without a "presence" statement, which has at
          least one mandatory node as a child.
    

    This should already be helpful for your second question.

    Is there maybe another way to model this scenario? (Without breaking "too much")

    Abuse presence containers. They are always optional. You could also probably avoid using the lists by introducing some mandatory children to a non-presence container. Based on your initial data:

    module mandatory-optional-branch {
      namespace "org:example:mandatory-optional-branch";
      prefix "mob";
    
      grouping leafs {
        leaf leaf1 {type string;}
        leaf leaf2 {type string;}
      }
    
      list namespace { // mandatory
        config false;
        min-elements 1;
        max-elements 1;
        container management { // optional by nature
          presence "I have mandatory children, but am not mandatory. Yay for me.
                    Of course my presence should have some meaning.";
          list interfaces { // mandatory
            min-elements 1;
            max-elements 1;
            container m0 { // optional - no mandatory node children
              leaf leaf1 {type string;}
            }
          }
        }
        container benchmark { // optional by nature
          presence "Same as 'management' above.";
          list interfaces { // mandatory
            min-elements 1;
            max-elements 1;
            container b0 { // optional - no mandatory node children
              uses leafs;
            }
            container b1 { // optional - no mandatory node children
              uses leafs;
            }
          }
        }
      }
    }