Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

This page documents the existing Yang Parser used in ONAP and OpenDayLight and will investigate if they can be used for it fulfill the needs of the C&PS.

Overview

The Yang parser used in ONAP (CCSDK / SDNC) was developed (and still is) a OpenDayLight Library.

...

The documentation mentioned above lists many modules but the code examples do not clarify which exactly are needed to parse a Yang model and Yang file data files in java code.

...


...

Code Block

...

xml
Code Block
language
languagexml
themeMidnight
titlepom.xml
collapsetrue
    <properties>
		
        <maven.compiler.version>3.8.1</maven.compiler.version>
		
        <maven.compiler.release>11</maven.compiler.release>
		<org.opendaylight
        <odl.yangtools.version>5.0.3<5</org.opendaylightodl.yangtools.version>
 	   </properties>

   	 	<build>
		<plugins>
			<plugin>
				        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
				
                <artifactId>maven-compiler-plugin</artifactId>
				                <version>${maven.compiler.version}</version>
				<configuration>
					
                <configuration>
                    <release>${maven.compiler.release}</release>
				                </configuration>
			
            </plugin>
		
        </plugins>
  	  </build>

    	<dependencies>
		<dependency>
			        <dependency>
            <groupId>org.opendaylight.yangtools</groupId>
			
            <artifactId>yang-parser-api</artifactId>
			<version>${org.opendaylight
            <version>${odl.yangtools.version}</version>
		
        </dependency>
 		<dependency>
			       <dependency>
            <groupId>org.opendaylight.yangtools</groupId>
			
            <artifactId>yang-parser-impl</artifactId>
			<version>${org.opendaylight.
            <version>${odl.yangtools.version}</version>
		</dependency>

		<dependency>
			        </dependency>
        <dependency>
            <groupId>org.opendaylight.yangtools</groupId>
			
            <artifactId>yang-model-util</artifactId>
			<version>${org.opendaylight
            <version>${odl.yangtools.version}</version>
		
        </dependency>

        		<dependency>
			
            <groupId>org.opendaylight.yangtools</groupId>
			
            <artifactId>yang-data-codec-xml</artifactId>
			<version>${org.opendaylight            <version>${odl.yangtools.version}</version>
		
        </dependency>
      		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.6.1</version>
		</dependency>

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.6.1</version>
		</dependency>
	</dependencies>

Documentation Code Updates

The sample code provided in the documentation is faulty (using == for assigning?!) and is using some long deprecated and even removed classes and methods.

Bug reported: https://jira.opendaylight.org/browse/DOCS-126

Code Block
languagejava
themeMidnight
titleCorrected Code
linenumberstrue
collapsetrue
    static YangParserFactory PARSER_FACTORY;

    static {  <dependency>
            <groupId>org.opendaylight.yangtools</groupId>
            <artifactId>yang-data-codec-gson</artifactId>
            <version>${odl.yangtools.version}</version>
        </dependency>
        <!-- SLF4J API -->
        <dependency>
             final Iterator<YangParserFactory> it = ServiceLoader.load(YangParserFactory.class).iterator();<groupId>org.slf4j</groupId>
            if (!it.hasNext()) {<artifactId>slf4j-api</artifactId>
            <version>1.6.1</version>
 throw new IllegalStateException("No YangParserFactory found");   </dependency>
     }   <!-- LOG4J -->
        PARSER_FACTORY<dependency>
= it.next();     }      <groupId>org...slf4j</groupId>
         File file = new File(ClassLoader.getSystemClassLoader().getResource("example.yang").getFile());<artifactId>slf4j-log4j12</artifactId>
         YangTextSchemaSource source = YangTextSchemaSource.forFile(file);<version>1.6.1</version>
        </dependency>
        final YangParser yangParser = PARSER_FACTORY.createParser(StatementParserMode.</dependencies>

Note. SLF4J has also been added as the implementation requires an enabled logger

Documentation Code Updates

The sample code provided in the documentation is faulty (using == for assigning?!) and is using some long deprecated and even removed classes and methods.

Bug reported: https://jira.opendaylight.org/browse/DOCS-126

Code Block
languagejava
themeMidnight
titleCorrected Code
linenumberstrue
collapsetrue
    static YangParserFactory PARSER_FACTORY;

    static {
        final Iterator<YangParserFactory> it = ServiceLoader.load(YangParserFactory.class).iterator();
        if (!it.hasNext()) {
            throw new IllegalStateException("No YangParserFactory found");
        }
        PARSER_FACTORY = it.next();
    }

    ...

        File file = new File(ClassLoader.getSystemClassLoader().getResource("example.yang").getFile());
        YangTextSchemaSource source = YangTextSchemaSource.forFile(file);
        
        final YangParser yangParser = PARSER_FACTORY.createParser(StatementParserMode.DEFAULT_MODE);
        yangParser.addSource(source);
        SchemaContext schemaContext = yangParser.buildEffectiveModel();

        schemaContext.getModules()

...

DescriptionYangJava Object ViewNotesXML Validation

JSON
Validation

Datatypes and basic constraints

Basic String

leaf response-code {
  type string;
}

TypeStatement TypeAwareDeclaredStatement.getType()YesYes
Mandatory Basic String

leaf response-code {925px
  type string;
    mandatory "true";
}

Optional<MandatoryStatement> MandatoryStatementAwareDeclaredStatement.getMandatory()

NoNo
Limited String leaf pnf-name {
  type string {
    length "0..256";
}

Optional<LengthConstraint> AbstractLengthRestrictedType.getLengthConstraint()

YesYes
typedef (String) with pattern

typedef dotted-quad {
  type string {
pattern
  '(([0-9] ...';
  }
}

leaf address {
   type dotted-quad;
   mandatory "true";
}

List<PatternConstraint> RestrictedStringType.getPatternConstraints()YesYes
Limited uint64 leaf cid {
  type uint64 {
     range "0..503";
  }
}

org.opendaylight.yangtools.yang.model.util.type.RestrictedUint64TypeYesYes
boolean with default value

leaf blacklisted {
  type boolean;
  default 1;
}

org.opendaylight.yangtools.yang.model.util.type.DerivedBooleanTypeN/AN/A

Unique

Unique list server {
  key "name";
  unique "ip port";
  leaf name {
    type string;
  }
  leaf ip {
    type dotted-quad;
  }
  leaf port {
    type uint32;
  }}

org.opendaylight.yangtools.yang.model.api.stmt.UniqueStatementNoNo

Choice

Choicechoice transfer-method {
  leaf transfer-interval {
    type uint64 { range "15..2880"; }
    units minutes; }
  leaf transfer-on-commit {
  type empty;
  }}

org.opendaylight.yangtools.yang.model.api.stmt.ChoiceStatementN/AN/A

Must

Must leaf ifType {
type enumeration {
enum ethernet;
enum atm;}}
leaf ifMTU {
type uint32;}
must "ifType != 'ethernet' or "
+ "(ifType = 'ethernet' and ifMTU = 1500)"
{
error-message 466px"An ethernet MTU must be 1500";}

org.opendaylight.yangtools.yang.model.api.stmt.ErrorMessageStatementNoNo

When

When
leaf a {
    type boolean;
}
leaf b {
    type string;
    when "../a = 'true'";
}

org.opendaylight.yangtools.yang.model.api.stmt.WhenStatementNoNo

Extension

Extension declaration

extension store-state-ext {
argument duration;
description "An extension to enable
state-storage for any attribute.
Use duration to specify how long: nnn h|d|y";

}


N/A
Extension usage leaf attribute-with-temporal-storage {
  type string;
  cm-notify-api:store-state-ext "3 d";
// store state 3 days

}

extension is stored as 'UnknownNode' and refers back to the extension declarationN/A

Augmentation


augment "server" {
  when "port = '8787'";
    leaf enable-debug {
      type boolean;
    }
}


N/A

RPC

rpc
rpc nbrlist-change-notification {
description
"RAN Neighbor List change notification to configure RuntimeDB";
input {
:
}
output {
:
}
}


N/A
rpc input
 input {
leaf fap-service-number-of-entries-changed {
type uint64;
description
"Number of cells for which neighbor list has changed";
}
list fap-service {
key "alias";
leaf alias {
type string {
length "1..64";
}
}
leaf cid {
type string {
length "0..52";
}
}
uses x-0005b9-lte-g;
leaf lte-cell-number-of-entries {
type uint64;
description
"Number of cells in a neighbor list that was changed";
}
list lte-ran-neighbor-list-in-use-lte-cell-changed {
key "plmnid cid";
uses lte-ran-neighbor-list-in-use-lte-cell-g;
description
"Changed/Modified List of cells
in a neighbor list for this fap service";
     }
}
}


N/A
rpc output
output {
uses cm-notification-response;
}


N/A

Yang Data Parsing and

...

Validation

XML Parsing

Code Block
languagejava
themeMidnight
titleXML Parsing Example
linenumberstrue
collapsetrue
		SchemaContext schemaContext = ... (see previous snippets)
        final Module module = schemaContext.findModules("ultraconfig-interfaces").iterator().next();
        QName qName = QName.create(module.getQNameModule(),"interfaces");
        final Optional<DataSchemaNode> node = module.findDataChildByName(qName);
        if (node.isPresent()) {
            final InputStream resourceAsStream = ClassLoader.getSystemClassLoader().getResourceAsStream("example2data.xml");
            final XMLStreamReader reader = UntrustedXML.createXMLStreamReader(resourceAsStream);
            final NormalizedNodeResult result = new NormalizedNodeResult();
            final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
            final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, schemaContext, node.get() );
            xmlParser.parse(reader);
            final NormalizedNode<?, ?> transformedInput = result.getResult();
        }

...

  • As expected the parsing of string, originating form XML or JSON is done by the same code and the results are identical to those for XML Data Parsing

Conclusions

...

  • for XML Data Parsing

Conclusion

Pros

  1. The YangTools model parser is comprehensive and covers all possible Yang Language elements we might require
  2. Extensively used throughout ONAP and ODL projects
  3. Mature code, dates back to 2013 with contributions from many companies including Cisco and Redhat
  4. Parsing of JSON and XML data with validated for a a (parsed) model included

Cons

  1. Due to its completeness it also is a complicated piece of software which will take some time to get familiar with
  2. Documentation out of date, this page hopes to address that somewhat