restrict yang leafref key identifier without extra leaf - ietf-netmod-yang

I have a yang model with a leafref, which is pointing to a list inside of a other list.
Basically something like this:
list some-names
{
key "name";
leaf name
{
type string;
}
list some-other-names
{
key "name";
leaf name
{
type string;
}
}
}
I want to point from outside with a leafref to the some-other-names list but only the ones with upper name equals to foo.
Unfortunately the leafref has to have a current() for restriction.
So my current solution is the following but requires a extra leaf which
is total unnecessary for configuration .
leaf foo
{
type string;
deafault "foo";
}
leaf some-leaf-ref
{
type leafref
{
path "/some-names[name = current()/../foo]/some-other-names/name";
}
}
Is there a simpler way than this, which does not need a additional leaf for restricting the name of some-names to a certain value?
BTW this I already tried but its not a correct path-arg:
leaf some-leaf-ref
{
type leafref
{
path "/some-names[name = 'foo']/some-other-names";
}
}

Perhaps something along the lines of:
leaf some-leafref {
must "/some-names[name = 'foo']/some-other-names/name = .";
type leafref {
path "/some-names/some-other-names/name";
}
}
So, no predicate in the path expression, yet with an additional must restriction - the two expressions are essentially ANDed together. YANG specification does mention that a path expression may evaluate to a node set that contains more than one node, and it doesn't say predicates are mandatory per key (unlike for instance-identifiers). Seems like hackery to me, though, or ugly at least.
Perhaps what you really want is a leafref leaf child to your outer list (some-names), that has a when to make it valid only when ../name = 'foo'.
list some-names {
key "name";
leaf name {
type string;
}
list some-other-names {
key "name";
leaf name {
type my-type;
}
}
leaf some-leafref {
when "../name = 'foo'";
type leafref {
path "../some-other-names/name";
}
}
}

Related

Is it possible to use two When statements in a Yang model

Trying to use one Yang leaf with two different if-types depending on the value given.
Currently have:
leaf interface_number {
when "boolean(string(/payload/interface_type) != 'ae')";
type isyt:interface_number_value;
when "boolean(string(/payload/interface_type) == 'ae')";
type isyt:interface_lag_value;
description
"Interface Number. Example value: 1/1/1 or 11 for LAG";
mandatory "true";
}
I have also tried:
leaf interface_number {
when "boolean(string(/payload/interface_type) != 'ae')" {
type isyt:interface_number_value;
}
when "boolean(string(/payload/interface_type) == 'ae')" {
type isyt:interface_lag_value;
}
description
"Interface Number. Example value: 1/1/1 or 11 for LAG";
mandatory "true";
}
Yang seems to accept the first when they errors on the second when statements' boolean.
Is this even possible? or is there a better method to use for this.
That's not how the YANG syntax works; the type statement cannot be conditional upon the when. The when affects the whole enclosing node, so if it evaluates to false, your interface_number would not be valid at all.
What you can do here is to create a choice whose case statements are when-conditional depending on the type of the ../interface_type leaf. This will need a different name for each of the leaf that you define within these case statements.

alternative way to use boolean container

container first{
container second{
type boolean;
}
}
how can i do something like this.(My error:i can't boolean a container/error: unexpected keyword "type") I don't want to use leaf. Is there an alternative ?
As per RFC 6020. For storing single data we have to use leaf. Using containers to store boolean data, I don't think would be possible.
As per RFC6020 section 7.5.1, Containers are used to organize the hierarchy of data nodes, and those whose presence in the configuration has an explicit meaning.It means we can't use container to store the data.
If you don't want to use boolean then you can try to use "enum" like this:
leaf myenum {
type enumeration {
enum zero {
value 0;
}
enum one {
value 1;
}
}
}
.

How to augment list from one module to another and add leafs YANG

Suppose I have two modules, I would like to extend one list with new leafs.
module A {
list deviceList {
key name;
leaf name{
}
leaf hostname{
}
}
}
and I would like to augment it to another leaf
module B {
list generalInfo{
key customerName;
leaf customerName{
type string;
}
augment moduleA:deviceList {
leaf ipAddress{
}
}
}
I have done it using grouping and container and list inside but this completely changes our existing structure, I would like to ommit container and grouping if thats possible.
It seems that you want to reuse a part of the schema definition, put it in another place in the schema tree and add a node to it.
You cannot do it the way you tried because the augment statement can appear only on the root level or in the uses statement.
You can do that only with a grouping but you can omit the container. Refactor A: define a grouping that's a list. Refer to it in B and augment it.
module A {
grouping devices {
list deviceList {
key name;
leaf name{
}
leaf hostname{
}
}
}
uses devices;
}
module B {
list generalInfo{
key customerName;
leaf customerName{
type string;
}
uses moduleA:devices {
augment "deviceList" {
leaf ipAddress{
}
}
}
}
}
Note that if you use the augment statement in the module B then it means that any device implementing module B has to also implement module A and its root-level list deviceList. See RFC 7950 4.2.8:
When a server implements a module containing an "augment" statement,
that implies that the server's implementation of the augmented module
contains the additional nodes.
I am not sure if this is what you want. If not, then move the grouping definition to a module that contains only grouping definitions (without any "data definition statements") and import it from both A and B.

Content checking some, not all, class attributes

I have a class with attributes. I want to check whether some but not all are defined. So:
class A {
has $.a is rw;
has $.b is rw;
has $.c is rw;
has $.d is rw;
method delete { ... }
}
my A $x .= new(:a<hi>, :d<good>);
## later
$x.b = 'there';
## code in which $x.c may or may not be defined.
## now I want to check if the attributes a, b, and c are defined, without
## needing to know about d
my Bool $taint = False;
for <a b c> {
$taint &&= $x.$_.defined
}
This will cause errors because an object of type A doesn't have a method 'CALL-ME' for type string.
Is there an introspection method that gives me the values of attributes of a class?
$x.^attributes gives me their names and types, but not their values.
I think there must be some way since dd or .perl provide attribute values - I think.
Yes, it is called get_value. It needs the object of the attribute passed to it. For example:
class A {
has $.a = 42;
has $.b = 666;
}
my $a = A.new;
for $a.^attributes -> $attr {
say "$attr.name(): $attr.get_value($a)"
}
# $!a: 42
# $!b: 666

Yang Model recursive search for must condition

I have a problem with a restriction on my CLI. I've been investigating yang RFC7950 (https://www.rfc-editor.org/rfc/rfc7950) but I've found nothing.
Here is an example.
grouping httpGroup {
list http-list{
key "value";
leaf value {
status current { yexte:preliminary; }
description "value to match";
must "(not(../protocol)) and (not(../network-port)))" {
error-message "Not compatible with protocol or non-TCP ports";
}
type string { length "1..255"; }
}
}
}
This group will be included in several groups with the following structure:
list and {
leaf-list protocol { ..... }
uses A;
list or {
leaf-list protocol { ..... }
uses A;
}
}
grouping A {
status{}
leaf-list protocol { ..... }
leaf-list X { ..... }
uses httpGroup;
}
I need this must condition included in httpGroup to verify that protocol value has not been configured in any level of the hierarchy.
I've made this be adding more relatives paths to search for this node:
// same level
not(../protocol)
// next level
not(../and/protocol)
not(../or/protocol)
// previous level
not(../../protocol)
not(../../protocol)
//recursively down previous level
not(../../and/protocol)
not(../../or/protocol)
// third level
not(../and/or/protocol)
not(../and/and/protocol)
As you can see, this is not a clean solution at all.
Is there any way it can be done for a whole hierarchy like:
if protocol node exists and http-list exists then error.
Thank you in advance.
Groupings are meant to be reusable. It is a bad practice to attempt to create a grouping that may only be used in specific contexts. This is exactly what happens if you define an XPath expression within a grouping and this expression references nodes that are "outside" this grouping (a not yet known ancestor data node, for example, or even worse - an ancestor with a specific name).
The proper way for you to handle this situation would be to use a refine statement in each different context where this grouping is used. You target the value leaf with it, then refine it by adding a must statement, the expression of which of course depends on usage context. You do not define a must statement within grouping http-list.
Within grouping A:
grouping A {
status{}
leaf-list protocol { ..... }
leaf-list X { ..... }
uses httpGroup {refine "http-list/value" {must "not(../../protocol)";}}
}
As you can see, grouping A is now completely self-sufficient and may be used within any context - the must will not have any problems with it.