<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>${slf4j.version}</version>
+ <scope>test</scope>
+ </dependency>
<!-- Supporting Libraries -->
<dependency>
</dependencies>
</dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ </dependency>
+ </dependencies>
+
<distributionManagement>
<!-- OpenDayLight Released artifact -->
<repository>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>${maven.release.version}</version>
+
+ <!-- Since we have a maven plugin, we need to install it -->
+ <configuration>
+ <preparationGoals>clean install</preparationGoals>
+ <completionGoals>clean install</completionGoals>
+ </configuration>
</plugin>
</plugins>
</pluginManagement>
<artifactId>antlr4-runtime</artifactId>
<version>4.0</version>
</dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-simple</artifactId>
- <version>1.7.2</version>
- <scope>test</scope>
- </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
string : STRING (PLUS STRING)*;
identifier_stmt : IDENTIFIER string? stmtend;
-
+unknown_statement : (YIN_ELEMENT_KEYWORD | YANG_VERSION_KEYWORD | WHEN_KEYWORD | VALUE_KEYWORD | USES_KEYWORD | UNITS_KEYWORD | UNIQUE_KEYWORD |
+ TYPEDEF_KEYWORD | TYPE_KEYWORD | SUBMODULE_KEYWORD | RPC_KEYWORD | REVISION_DATE_KEYWORD | REVISION_KEYWORD |
+ REQUIRE_INSTANCE_KEYWORD | REFINE_KEYWORD | RANGE_KEYWORD | PRESENCE_KEYWORD | PREFIX_KEYWORD |
+ POSITION_KEYWORD | PATTERN_KEYWORD | PATH_KEYWORD | OUTPUT_KEYWORD | ORGANIZATION_KEYWORD| ORDERED_BY_KEYWORD | NOTIFICATION_KEYWORD|
+ NAMESPACE_KEYWORD | MUST_KEYWORD | MODULE_KEYWORD | MIN_ELEMENTS_KEYWORD | MAX_ELEMENTS_KEYWORD | MANDATORY_KEYWORD | LIST_KEYWORD |
+ LENGTH_KEYWORD | LEAF_LIST_KEYWORD | LEAF_KEYWORD | KEY_KEYWORD | INPUT_KEYWORD | INCLUDE_KEYWORD | IMPORT_KEYWORD | IF_FEATURE_KEYWORD |
+ IDENTITY_KEYWORD | GROUPING_KEYWORD | FRACTION_DIGITS_KEYWORD | FEATURE_KEYWORD | DEVIATE_KEYWORD | DEVIATION_KEYWORD | EXTENSION_KEYWORD |
+ ERROR_MESSAGE_KEYWORD | ERROR_APP_TAG_KEYWORD | ENUM_KEYWORD | DEFAULT_KEYWORD | CONTAINER_KEYWORD | CONTACT_KEYWORD |
+ CONFIG_KEYWORD | CHOICE_KEYWORD | CASE_KEYWORD | BIT_KEYWORD | BELONGS_TO_KEYWORD | BASE_KEYWORD | AUGMENT_KEYWORD |
+ ANYXML_KEYWORD | IDENTIFIER) string? (SEMICOLON | (LEFT_BRACE unknown_statement2* RIGHT_BRACE));
+
+unknown_statement2 : (YANG_VERSION_KEYWORD | WHEN_KEYWORD | VALUE_KEYWORD | USES_KEYWORD | UNITS_KEYWORD | UNIQUE_KEYWORD |
+ TYPEDEF_KEYWORD | TYPE_KEYWORD | SUBMODULE_KEYWORD | STATUS_KEYWORD | RPC_KEYWORD | REVISION_DATE_KEYWORD | REVISION_KEYWORD |
+ REQUIRE_INSTANCE_KEYWORD | REFINE_KEYWORD | REFERENCE_KEYWORD | RANGE_KEYWORD | PRESENCE_KEYWORD | PREFIX_KEYWORD |
+ POSITION_KEYWORD | PATTERN_KEYWORD | PATH_KEYWORD | OUTPUT_KEYWORD | ORGANIZATION_KEYWORD| ORDERED_BY_KEYWORD | NOTIFICATION_KEYWORD|
+ NAMESPACE_KEYWORD | MUST_KEYWORD | MODULE_KEYWORD | MIN_ELEMENTS_KEYWORD | MAX_ELEMENTS_KEYWORD | MANDATORY_KEYWORD | LIST_KEYWORD |
+ LENGTH_KEYWORD | LEAF_LIST_KEYWORD | LEAF_KEYWORD | KEY_KEYWORD | INPUT_KEYWORD | INCLUDE_KEYWORD | IMPORT_KEYWORD | IF_FEATURE_KEYWORD |
+ IDENTITY_KEYWORD | GROUPING_KEYWORD | FRACTION_DIGITS_KEYWORD | FEATURE_KEYWORD | DEVIATE_KEYWORD | DEVIATION_KEYWORD | EXTENSION_KEYWORD |
+ ERROR_MESSAGE_KEYWORD | ERROR_APP_TAG_KEYWORD | ENUM_KEYWORD | DESCRIPTION_KEYWORD | DEFAULT_KEYWORD | CONTAINER_KEYWORD | CONTACT_KEYWORD |
+ CONFIG_KEYWORD | CHOICE_KEYWORD | CASE_KEYWORD | BIT_KEYWORD | BELONGS_TO_KEYWORD | BASE_KEYWORD | AUGMENT_KEYWORD | ARGUMENT_KEYWORD |
+ ANYXML_KEYWORD | IDENTIFIER) string? (SEMICOLON | (LEFT_BRACE unknown_statement3* RIGHT_BRACE));
+
+unknown_statement3 : (YIN_ELEMENT_KEYWORD | YANG_VERSION_KEYWORD | WHEN_KEYWORD | VALUE_KEYWORD | USES_KEYWORD | UNITS_KEYWORD | UNIQUE_KEYWORD |
+ TYPEDEF_KEYWORD | TYPE_KEYWORD | SUBMODULE_KEYWORD | STATUS_KEYWORD | RPC_KEYWORD | REVISION_DATE_KEYWORD | REVISION_KEYWORD |
+ REQUIRE_INSTANCE_KEYWORD | REFINE_KEYWORD | REFERENCE_KEYWORD | RANGE_KEYWORD | PRESENCE_KEYWORD | PREFIX_KEYWORD |
+ POSITION_KEYWORD | PATTERN_KEYWORD | PATH_KEYWORD | OUTPUT_KEYWORD | ORGANIZATION_KEYWORD| ORDERED_BY_KEYWORD | NOTIFICATION_KEYWORD|
+ NAMESPACE_KEYWORD | MUST_KEYWORD | MODULE_KEYWORD | MIN_ELEMENTS_KEYWORD | MAX_ELEMENTS_KEYWORD | MANDATORY_KEYWORD | LIST_KEYWORD |
+ LENGTH_KEYWORD | LEAF_LIST_KEYWORD | LEAF_KEYWORD | KEY_KEYWORD | INPUT_KEYWORD | INCLUDE_KEYWORD | IMPORT_KEYWORD | IF_FEATURE_KEYWORD |
+ IDENTITY_KEYWORD | GROUPING_KEYWORD | FRACTION_DIGITS_KEYWORD | FEATURE_KEYWORD | DEVIATE_KEYWORD | DEVIATION_KEYWORD | EXTENSION_KEYWORD |
+ ERROR_MESSAGE_KEYWORD | ERROR_APP_TAG_KEYWORD | ENUM_KEYWORD | DESCRIPTION_KEYWORD | DEFAULT_KEYWORD | CONTAINER_KEYWORD | CONTACT_KEYWORD |
+ CONFIG_KEYWORD | CHOICE_KEYWORD | CASE_KEYWORD | BIT_KEYWORD | BELONGS_TO_KEYWORD | BASE_KEYWORD | AUGMENT_KEYWORD | ARGUMENT_KEYWORD |
+ ANYXML_KEYWORD | IDENTIFIER) string? (SEMICOLON | (LEFT_BRACE unknown_statement3* RIGHT_BRACE));
+
stmtend : (SEMICOLON) | (LEFT_BRACE identifier_stmt? RIGHT_BRACE);
deviate_replace_stmt : DEVIATE_KEYWORD string /* REPLACE_KEYWORD */ (SEMICOLON | (LEFT_BRACE (identifier_stmt |type_stmt | units_stmt | default_stmt | config_stmt | mandatory_stmt | min_elements_stmt | max_elements_stmt )* RIGHT_BRACE));
deviate_delete_stmt : DEVIATE_KEYWORD string /* DELETE_KEYWORD */ (SEMICOLON | (LEFT_BRACE (identifier_stmt |units_stmt | must_stmt | unique_stmt | default_stmt )* RIGHT_BRACE));
identity_stmt : IDENTITY_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt | base_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
yin_element_arg : string; // TRUE_KEYWORD | FALSE_KEYWORD;
yin_element_stmt : YIN_ELEMENT_KEYWORD yin_element_arg stmtend;
-argument_stmt : ARGUMENT_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt)? (yin_element_stmt )? (identifier_stmt)* RIGHT_BRACE));
-extension_stmt : EXTENSION_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt | argument_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
+argument_stmt : ARGUMENT_KEYWORD string (SEMICOLON | (LEFT_BRACE (unknown_statement2)? (yin_element_stmt)? RIGHT_BRACE));
+extension_stmt : EXTENSION_KEYWORD string (SEMICOLON | (LEFT_BRACE (unknown_statement | argument_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
revision_date_stmt : REVISION_DATE_KEYWORD string stmtend;
revision_stmt : REVISION_KEYWORD string (SEMICOLON | (LEFT_BRACE (description_stmt )? (reference_stmt )? RIGHT_BRACE));
units_stmt : UNITS_KEYWORD string stmtend;
public static Set<Module> loadModules(String resourceDirectory) throws FileNotFoundException {
YangModelParser parser = new YangParserImpl();
+ return loadModules(resourceDirectory, parser);
+ }
+
+ public static Set<Module> loadModules(String resourceDirectory, YangModelParser parser) throws FileNotFoundException {
final File testDir = new File(resourceDirectory);
final String[] fileList = testDir.list();
final List<File> testFiles = new ArrayList<>();
}
}
+ public static List<Module> findModules(Set<Module> modules, String moduleName) {
+ List<Module> result = new ArrayList<>();
+ for (Module module : modules) {
+ if (module.getName().equals(moduleName)) {
+ result.add(module);
+ }
+ }
+ return result;
+ }
+
}
--- /dev/null
+package org.opendaylight.yangtools.yang.parser.impl;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+
+public class TwoRevisionsTest {
+
+ @Test
+ public void testTwoRevisions() throws Exception {
+ YangModelParser parser = new YangParserImpl();
+
+ Set<Module> modules = TestUtils.loadModules(getClass().getResource("/ietf").getPath(), parser);
+ assertEquals(2, TestUtils.findModules(modules, "network-topology").size());
+
+ SchemaContext schemaContext = parser.resolveSchemaContext(modules);
+ assertEquals(2, TestUtils.findModules(schemaContext.getModules(), "network-topology").size());
+
+ }
+
+}
--- /dev/null
+module network-topology {
+ yang-version 1;
+ namespace "urn:TBD:params:xml:ns:yang:network-topology";
+ // replace with IANA namespace when assigned
+ prefix "nt";
+
+ import ietf-inet-types { prefix "inet"; }
+
+ organization "TBD";
+
+ contact "WILL-BE-DEFINED-LATER";
+/*
+ description
+ "This module defines a model for the topology of a network.
+ Key design decisions are as follows:
+ A topology consists of a set of nodes and links.
+ Links are point-to-point and unidirectional.
+ Bidirectional connections need to be represented through
+ two separate links.
+ Multipoint connections, broadcast domains etc can be represented
+ through a hierarchy of nodes, then connecting nodes at
+ upper layers of the hierarchy.";
+*/
+ revision 2013-07-12 {
+ description
+ "Initial revision.";
+ }
+
+ typedef topology-id {
+ type inet:uri;
+ description
+ "An identifier for a topology.";
+ }
+
+ typedef node-id {
+ type inet:uri;
+ description
+ "An identifier for a node in a topology.
+ The identifier may be opaque.
+ The identifier SHOULD be chosen such that the same node in a
+ real network topology will always be identified through the
+ same identifier, even if the model is instantiated in separate
+ datastores. An implementation MAY choose to capture semantics
+ in the identifier, for example to indicate the type of node
+ and/or the type of topology that the node is a part of.";
+ }
+
+ typedef link-id {
+ type inet:uri;
+ description
+ "An identifier for a link in a topology.
+ The identifier may be opaque.
+ The identifier SHOULD be chosen such that the same link in a
+ real network topology will always be identified through the
+ same identifier, even if the model is instantiated in separate
+ datastores. An implementation MAY choose to capture semantics
+ in the identifier, for example to indicate the type of link
+ and/or the type of topology that the link is a part of.";
+ }
+
+ typedef tp-id {
+ type inet:uri;
+ description
+ "An identifier for termination points on a node.
+ The identifier may be opaque.
+ The identifier SHOULD be chosen such that the same TP in a
+ real network topology will always be identified through the
+ same identifier, even if the model is instantiated in separate
+ datastores. An implementation MAY choose to capture semantics
+ in the identifier, for example to indicate the type of TP
+ and/or the type of node and topology that the TP is a part of.";
+ }
+
+ typedef tp-ref {
+ type leafref {
+ path "/network-topology/topology/node/termination-point/tp-id";
+ }
+ description
+ "A type for an absolute reference to a termination point.
+ (This type should not be used for relative references.
+ In such a case, a relative path should be used instead.)";
+ }
+ typedef topology-ref {
+ type leafref {
+ path "/network-topology/topology/topology-id";
+ }
+ description
+ "A type for an absolute reference a topology instance.";
+ }
+
+ typedef node-ref {
+ type leafref {
+ path "/network-topology/topology/node/node-id";
+ }
+ description
+ "A type for an absolute reference to a node instance.
+ (This type should not be used for relative references.
+ In such a case, a relative path should be used instead.)";
+ }
+
+ typedef link-ref {
+ type leafref {
+ path "/network-topology/topology/link/link-id";
+ }
+ description
+ "A type for an absolute reference a link instance.
+ (This type should not be used for relative references.
+ In such a case, a relative path should be used instead.)";
+ }
+
+ grouping tp-attributes {
+ description
+ "The data objects needed to define a termination point.
+ (This only includes a single leaf at this point, used
+ to identify the termination point.)
+ Provided in a grouping so that in addition to the datastore,
+ the data can also be included in notifications.";
+ leaf tp-id {
+ type tp-id;
+ }
+ leaf-list tp-ref {
+ type tp-ref;
+ config false;
+ description
+ "The leaf list identifies any termination points that the
+ termination point is dependent on, or maps onto.
+ Those termination points will themselves be contained
+ in a supporting node.
+ This dependency information can be inferred from
+ the dependencies between links. For this reason,
+ this item is not separately configurable. Hence no
+ corresponding constraint needs to be articulated.
+ The corresponding information is simply provided by the
+ implementing system.";
+ }
+ }
+
+ grouping node-attributes {
+ description
+ "The data objects needed to define a node.
+ The objects are provided in a grouping so that in addition to
+ the datastore, the data can also be included in notifications
+ as needed.";
+ leaf node-id {
+ type node-id;
+ description
+ "The identifier of a node in the topology.
+ A node is specific to a topology to which it belongs.";
+ }
+ list supporting-node {
+ description
+ "This list defines vertical layering information for nodes.
+ It allows to capture for any given node, which node (or nodes)
+ in the corresponding underlay topology it maps onto.
+ A node can map to zero, one, or more nodes below it;
+ accordingly there can be zero, one, or more elements in the list.
+ If there are specific layering requirements, for example
+ specific to a particular type of topology that only allows
+ for certain layering relationships, the choice
+ below can be augmented with additional cases.
+ A list has been chosen rather than a leaf-list in order
+ to provide room for augmentations, e.g. for
+ statistics or priorization information associated with
+ supporting nodes.";
+ key "node-ref";
+ leaf node-ref {
+ type node-ref;
+ }
+ }
+ }
+
+ grouping link-attributes {
+ // This is a grouping, not defined inline with the link definition itself,
+ // so it can be included in a notification, if needed
+ leaf link-id {
+ type link-id;
+ description
+ "The identifier of a link in the topology.
+ A link is specific to a topology to which it belongs.";
+ }
+ container source {
+ leaf source-node {
+ mandatory true;
+ type node-ref;
+ description
+ "Source node identifier, must be in same topology.";
+ }
+ leaf source-tp {
+ type tp-ref;
+ description
+ "Termination point within source node that terminates the link.";
+ }
+ }
+ container destination {
+ leaf dest-node {
+ mandatory true;
+ type node-ref;
+ description
+ "Destination node identifier, must be in same topology.";
+ }
+ leaf dest-tp {
+ type tp-ref;
+ description
+ "Termination point within destination node that terminates the link.";
+ }
+ }
+ list supporting-link {
+ key "link-ref";
+ leaf link-ref {
+ type link-ref;
+ }
+ }
+ }
+
+
+ container network-topology {
+ list topology {
+ description "
+ This is the model of an abstract topology.
+ A topology contins nodes and links.
+ Each topology MUST be identified by
+ unique topology-id for reason that a network could contain many
+ topologies.
+ ";
+ key "topology-id";
+ leaf topology-id {
+ type topology-id;
+ description "
+ It is presumed that a datastore will contain many topologies. To
+ distinguish between topologies it is vital to have UNIQUE
+ topology identifiers.
+ ";
+ }
+ container topology-types {
+ description
+ "This container is used to identify the type, or types
+ (as a topology can support several types simultaneously),
+ of the topology.
+ Topology types are the subject of several integrity constraints
+ that an implementing server can validate in order to
+ maintain integrity of the datastore.
+ Topology types are indicated through separate data nodes;
+ the set of topology types is expected to increase over time.
+ To add support for a new topology, an augmenting module
+ needs to augment this container with a new empty optional
+ container to indicate the new topology type.
+ The use of a container allows to indicate a subcategorization
+ of topology types.
+ The container SHALL NOT be augmented with any data nodes
+ that serve a purpose other than identifying a particular
+ topology type.
+ ";
+ }
+ list underlay-topology {
+ key "topology-ref";
+ leaf topology-ref {
+ type topology-ref;
+ }
+ // a list, not a leaf-list, to allow for potential augmentation
+ // with properties specific to the underlay topology,
+ // such as statistics, preferences, or cost.
+ description
+ "Identifies the topology, or topologies, that this topology
+ is dependent on.";
+ }
+
+ list node {
+ description "The list of network nodes defined for the topology.";
+ key "node-id";
+ uses node-attributes;
+ must "boolean(../underlay-topology[*]/node[./supporting-nodes/node-ref])";
+ // This constraint is meant to ensure that a referenced node is in fact
+ // a node in an underlay topology.
+ list termination-point {
+ description
+ "A termination point can terminate a link.
+ Depending on the type of topology, a termination point could,
+ for example, refer to a port or an interface.";
+ key "tp-id";
+ uses tp-attributes;
+ }
+ }
+
+ list link {
+ description "
+ A Network Link connects a by Local (Source) node and
+ a Remote (Destination) Network Nodes via a set of the
+ nodes' termination points.
+ As it is possible to have several links between the same
+ source and destination nodes, and as a link could potentially
+ be re-homed between termination points, to ensure that we
+ would always know to distinguish between links, every link
+ is identified by a dedicated link identifier.
+ Note that a link models a point-to-point link, not a multipoint
+ link.
+ Layering dependencies on links in underlay topologies are
+ not represented as the layering information of nodes and of
+ termination points is sufficient.
+ ";
+ key "link-id";
+ uses link-attributes;
+ must "boolean(../underlay-topology/link[./supporting-link]";
+ // Constraint: any supporting link must be part of an underlay topology
+ must "boolean(../node[./source/source-node])";
+ // Constraint: A link must have as source a node of the same topology
+ must "boolean(../node[./destination/dest-node])";
+ // Constraint: A link must have as source a destination of the same topology
+ must "boolean(../node/termination-point[./source/source-tp])";
+ // Constraint: The source termination point must be contained in the source node
+ must "boolean(../node/termination-point[./destination/dest-tp])";
+ // Constraint: The destination termination point must be contained
+ // in the destination node
+ }
+ }
+ }
+}
--- /dev/null
+module network-topology {
+ yang-version 1;
+ namespace "urn:TBD:params:xml:ns:yang:network-topology";
+ // replace with IANA namespace when assigned
+ prefix "nt";
+
+ import ietf-inet-types { prefix "inet"; revision-date 2010-09-24; }
+
+ organization "TBD";
+
+ contact "WILL-BE-DEFINED-LATER";
+
+ description
+ "This module defines a model for the topology of a network.
+ Key design decisions are as follows:
+ A topology consists of a set of nodes and links.
+ Links are point-to-point and unidirectional.
+ Bidirectional connections need to be represented through
+ two separate links.
+ Multipoint connections, broadcast domains etc can be represented
+ through a hierarchy of nodes, then connecting nodes at
+ upper layers of the hierarchy.";
+
+ revision 2013-10-21 {
+ description
+ "Initial revision.";
+ }
+
+ typedef topology-id {
+ type inet:uri;
+ description
+ "An identifier for a topology.";
+ }
+
+ typedef node-id {
+ type inet:uri;
+ description
+ "An identifier for a node in a topology.
+ The identifier may be opaque.
+ The identifier SHOULD be chosen such that the same node in a
+ real network topology will always be identified through the
+ same identifier, even if the model is instantiated in separate
+ datastores. An implementation MAY choose to capture semantics
+ in the identifier, for example to indicate the type of node
+ and/or the type of topology that the node is a part of.";
+ }
+
+
+ typedef link-id {
+ type inet:uri;
+ description
+ "An identifier for a link in a topology.
+ The identifier may be opaque.
+ The identifier SHOULD be chosen such that the same link in a
+ real network topology will always be identified through the
+ same identifier, even if the model is instantiated in separate
+ datastores. An implementation MAY choose to capture semantics
+ in the identifier, for example to indicate the type of link
+ and/or the type of topology that the link is a part of.";
+ }
+
+ typedef tp-id {
+ type inet:uri;
+ description
+ "An identifier for termination points on a node.
+ The identifier may be opaque.
+ The identifier SHOULD be chosen such that the same TP in a
+ real network topology will always be identified through the
+ same identifier, even if the model is instantiated in separate
+ datastores. An implementation MAY choose to capture semantics
+ in the identifier, for example to indicate the type of TP
+ and/or the type of node and topology that the TP is a part of.";
+ }
+
+ typedef tp-ref {
+ type leafref {
+ path "/network-topology/topology/node/termination-point/tp-id";
+ }
+ description
+ "A type for an absolute reference to a termination point.
+ (This type should not be used for relative references.
+ In such a case, a relative path should be used instead.)";
+ }
+ typedef topology-ref {
+ type leafref {
+ path "/network-topology/topology/topology-id";
+ }
+ description
+ "A type for an absolute reference a topology instance.";
+ }
+
+ typedef node-ref {
+ type leafref {
+ path "/network-topology/topology/node/node-id";
+ }
+ description
+
+ "A type for an absolute reference to a node instance.
+ (This type should not be used for relative references.
+ In such a case, a relative path should be used instead.)";
+ }
+
+ typedef link-ref {
+ type leafref {
+ path "/network-topology/topology/link/link-id";
+ }
+ description
+ "A type for an absolute reference a link instance.
+ (This type should not be used for relative references.
+ In such a case, a relative path should be used instead.)";
+ }
+
+ grouping tp-attributes {
+ description
+ "The data objects needed to define a termination point.
+ (This only includes a single leaf at this point, used
+ to identify the termination point.)
+ Provided in a grouping so that in addition to the datastore,
+ the data can also be included in notifications.";
+ leaf tp-id {
+ type tp-id;
+ }
+ leaf-list tp-ref {
+ type tp-ref;
+ config false;
+ description
+ "The leaf list identifies any termination points that the
+ termination point is dependent on, or maps onto.
+ Those termination points will themselves be contained
+ in a supporting node.
+ This dependency information can be inferred from
+ the dependencies between links. For this reason,
+ this item is not separately configurable. Hence no
+ corresponding constraint needs to be articulated.
+ The corresponding information is simply provided by the
+ implementing system.";
+ }
+ }
+
+ grouping node-attributes {
+ description
+ "The data objects needed to define a node.
+ The objects are provided in a grouping so that in addition to
+ the datastore, the data can also be included in notifications
+ as needed.";
+
+ leaf node-id {
+ type node-id;
+ description
+ "The identifier of a node in the topology.
+ A node is specific to a topology to which it belongs.";
+ }
+ list supporting-node {
+ description
+ "This list defines vertical layering information for nodes.
+ It allows to capture for any given node, which node (or nodes)
+ in the corresponding underlay topology it maps onto.
+ A node can map to zero, one, or more nodes below it;
+ accordingly there can be zero, one, or more elements in the list.
+ If there are specific layering requirements, for example
+ specific to a particular type of topology that only allows
+ for certain layering relationships, the choice
+ below can be augmented with additional cases.
+ A list has been chosen rather than a leaf-list in order
+ to provide room for augmentations, e.g. for
+ statistics or priorization information associated with
+ supporting nodes.";
+ key "node-ref";
+ leaf node-ref {
+ type node-ref;
+ }
+ }
+ }
+
+ grouping link-attributes {
+ // This is a grouping, not defined inline with the link definition itself,
+ // so it can be included in a notification, if needed
+ leaf link-id {
+ type link-id;
+ description
+ "The identifier of a link in the topology.
+ A link is specific to a topology to which it belongs.";
+ }
+ container source {
+ leaf source-node {
+ mandatory true;
+ type node-ref;
+ description
+ "Source node identifier, must be in same topology.";
+ }
+ leaf source-tp {
+ type tp-ref;
+ description
+ "Termination point within source node that terminates the link.";
+
+ }
+ }
+ container destination {
+ leaf dest-node {
+ mandatory true;
+ type node-ref;
+ description
+ "Destination node identifier, must be in same topology.";
+ }
+ leaf dest-tp {
+ type tp-ref;
+ description
+ "Termination point within destination node that terminates the link.";
+ }
+ }
+ list supporting-link {
+ key "link-ref";
+ leaf link-ref {
+ type link-ref;
+ }
+ }
+ }
+
+
+ container network-topology {
+ list topology {
+ description "
+ This is the model of an abstract topology.
+ A topology contains nodes and links.
+ Each topology MUST be identified by
+ unique topology-id for reason that a network could contain many
+ topologies.
+ ";
+ key "topology-id";
+ leaf topology-id {
+ type topology-id;
+ description "
+ It is presumed that a datastore will contain many topologies. To
+ distinguish between topologies it is vital to have UNIQUE
+ topology identifiers.
+ ";
+ }
+ leaf server-provided {
+ type boolean;
+ config false;
+ description "
+ Indicates whether the topology is configurable by clients,
+ or whether it is provided by the server. This leaf is
+
+ populated by the server implementing the model.
+ It is set to false for topologies that are created by a client;
+ it is set to true otherwise. If it is set to true, any
+ attempt to edit the topology MUST be rejected.
+ ";
+ }
+ container topology-types {
+ description
+ "This container is used to identify the type, or types
+ (as a topology can support several types simultaneously),
+ of the topology.
+ Topology types are the subject of several integrity constraints
+ that an implementing server can validate in order to
+ maintain integrity of the datastore.
+ Topology types are indicated through separate data nodes;
+ the set of topology types is expected to increase over time.
+ To add support for a new topology, an augmenting module
+ needs to augment this container with a new empty optional
+ container to indicate the new topology type.
+ The use of a container allows to indicate a subcategorization
+ of topology types.
+ The container SHALL NOT be augmented with any data nodes
+ that serve a purpose other than identifying a particular
+ topology type.
+ ";
+ }
+ list underlay-topology {
+ key "topology-ref";
+ leaf topology-ref {
+ type topology-ref;
+ }
+ // a list, not a leaf-list, to allow for potential augmentation
+ // with properties specific to the underlay topology,
+ // such as statistics, preferences, or cost.
+ description
+ "Identifies the topology, or topologies, that this topology
+ is dependent on.";
+ }
+
+ list node {
+ description "The list of network nodes defined for the topology.";
+ key "node-id";
+ uses node-attributes;
+ must "boolean(../underlay-topology[*]/node[./supporting-nodes/node-ref])";
+ // This constraint is meant to ensure that a referenced node is in fact
+ // a node in an underlay topology.
+ list termination-point {
+ description
+
+ "A termination point can terminate a link.
+ Depending on the type of topology, a termination point could,
+ for example, refer to a port or an interface.";
+ key "tp-id";
+ uses tp-attributes;
+ }
+ }
+
+ list link {
+ description "
+ A Network Link connects a by Local (Source) node and
+ a Remote (Destination) Network Nodes via a set of the
+ nodes' termination points.
+ As it is possible to have several links between the same
+ source and destination nodes, and as a link could potentially
+ be re-homed between termination points, to ensure that we
+ would always know to distinguish between links, every link
+ is identified by a dedicated link identifier.
+ Note that a link models a point-to-point link, not a multipoint
+ link.
+ Layering dependencies on links in underlay topologies are
+ not represented as the layering information of nodes and of
+ termination points is sufficient.
+ ";
+ key "link-id";
+ uses link-attributes;
+ must "boolean(../underlay-topology/link[./supporting-link]";
+ // Constraint: any supporting link must be part of an underlay topology
+ must "boolean(../node[./source/source-node])";
+ // Constraint: A link must have as source a node of the same topology
+ must "boolean(../node[./destination/dest-node])";
+ // Constraint: A link must have as source a destination of the same topology
+ must "boolean(../node/termination-point[./source/source-tp])";
+ // Constraint: The source termination point must be contained in the source node
+ must "boolean(../node/termination-point[./destination/dest-tp])";
+ // Constraint: The destination termination point must be contained
+ // in the destination node
+ }
+ }
+ }
+}