摘要
YANG是一种数据建模语言,被用来为NETCONF,NETCONF远程过程调用,NETCONF Notification操作的配置和状态数据进行建模。
本文档状态
This is an Internet Standards Track document.
This document is a product of the Internet Engineering Task Force
(IETF). It represents the consensus of the IETF community. It has
received public review and has been approved for publication by the
Internet Engineering Steering Group (IESG). Further information on
Internet Standards is available in Section 2 of RFC 5741.
Information about the current status of this document, any errata,
and how to provide feedback on it may be obtained at
http://www.rfc-editor.org/info/rfc6020.
版权信息
Copyright (c) 2010 IETF Trust and the persons identified as the
document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust’s Legal
Provisions Relating to IETF Documents
(http://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents
carefully, as they describe your rights and restrictions with respect
to this document. Code Components extracted from this document must
include Simplified BSD License text as described in Section 4.e of
the Trust Legal Provisions and are provided without warranty as
described in the Simplified BSD License.
This document may contain material from IETF Documents or IETF
Contributions published or made publicly available before November
10, 2008. The person(s) controlling the copyright in some of this
material may not have granted the IETF Trust the right to allow
modifications of such material outside the IETF Standards Process.
Without obtaining an adequate license from the person(s) controlling
the copyright in such materials, this document may not be modified
outside the IETF Standards Process, and derivative works of it may
not be created outside the IETF Standards Process, except to format
it for publication as an RFC or to translate it into languages other
than English.
1. 介绍
YANG是一种数据建模语言,被用来为NETCONF,NETCONF远程过程调用,NETCONF Notification操作的配置和状态数据进行建模。
本文档描述了YANG语言的语法和语义,在一个YANG module中定义的数据模型如何以XML的形式表示,NETCONF如何操作数据。
2. 关键词
The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in BCP
14, [RFC2119].
3. 术语
anyxml —— 一种数据节点,能够包含未知的XML格式的数据块。
augment —— 向之前定义的schema node增加新的schema nodes。
base type —— 可以被用来继承的数据类型,可以使built-in类型,也可以是派生的类型。
built-in type —— YANG语言定义的YANG数据类型,比如uint32 或者 string。
choice —— 一个schema node,其值是多个可选项中的一个。
configuration data —— 可写入的数据的集合,被用来转变系统的状态【RFC4741】。
conformance(一致性) —— 一种评估实际上设备在多大程度上服从数据模型的方法。
container —— 一种内建的数据节点,在data tree中,最多只能有一个实例存在。一个container没有值,不过会包含一些子节点。
data definition statement —— 一种定义新的数据节点的声明(statement)。可以是container,leaf,leaf-list,list,choice,case,augment,uses,以及anyxml中的一个。
data model —— 一种表述数据如何展现和访问的数据模型。
data node(数据节点) —— schema tree中的一个节点,能够在data tree中实例化。可以是container,leaf,leaf-list,list,以及anyxml中的一个。
data tree —— 由一个设备上的配置和状态数据实例化的树。
derived type(派生类型) —— 一种从内建数据类型,或者其他派生类型中派生出来的类型。
device deviation(设备偏差) —— 如实反映设备在实现YANG模块时候的失败情况。
extension —— 使用非YANG语义声明的扩展。扩展声明定义了新的statement表示这些语义。
feature —— 一种可选的能够标记模型的某一部分的机制。可以使用feature名作为标签,不过该标签仅仅在支持该feature的设备上才有效。
grouping —— 一种可重用的schema nodes的集合。该集合可能在定义处的module中被使用,也可能在包含它的modules中使用,还可能在导入它的modules中被使用。grouping声明不是一种数据定义声明,它不会在schema node中定义任何节点。
identifier —— 通过名字,被用来识别不同种类的YANG items。
instance identifier —— 在data tree中被用来标记特定的一个节点。
interior node —— 分层结构中,非leaf node的节点。
leaf —— 一种数据节点,在data tree中最多只能有一个实例存在。一个leaf节点只能有一个值,并且不能有子节点。
leaf-list —— 和leaf节点相似,但是定义了一集合的可唯一识别的节点,而非一个节点。其中每一个节点都有值,但是都没有子节点。
list —— 一种内部的数据节点,在data tree中可能会有多个实例存在。一个list没有值,但是会有一些子节点。
module —— 一个YANG module定义了一个具有垂直层级结构的节点集,这些节点能够被用于基于NETCONF的operations。如果有一个module的定义,以及该module依赖的其他module的定义,则这个module是自足的,以及“可编译的(compilable)”。
RPC —— 远程过程调用,在NETCONF协议中使用的。
RPC operation —— 一种特定的远程过程调用,在NETCONF协议中使用的。也被成为协议操作(protocol operation)。
schema node —— 在schema tree中的节点。是container,leaf,leaf-list,list,choice,case,rpc,input,output,notification,以及anyxml中的一种。
schema tree —— module中的特定垂直结构定义(The definition hierarchy specified within a module.)。
state data(状态数据) —— 系统中的配置数据之外的其他额外数据,比如只读的状态信息,数据统计信息【RFC4741】。
submodule —— 一种局部的module定义。submodule为所在的module提供了derived types,groupings,data nodes,RPCs,以及notifications。一个YANG module可以由多个submodules组成。
top-level data node —— 一个数据节点,在该节点和module/submodule声明之间,没有其他的数据节点存在。
uses —— 这个“uses”声明被用来实例化在grouping声明中定义的schema nodes。这些实例化的节点可能会被扩展以满足特定的需求。
搞不明白feature的具体用法。不知道data tree和schema tree的区别。
3.1 Mandatory Nodes(必须出现的节点)
一个mandatory node是以下中的:
“mandatory”声明为“true”的一个leaf,choice,或者anyxml节点。
“min-elements”声明为大于0的数的一个list,或者leaf-list节点。
没有“presence”声明的container节点,它里面至少要包含一个mandatory node的子节点。
YANG是一种被用来为NETCONF协议建模的语言。一个YANG module定义了具有垂直结构的数据,这些数据可以被用做基于NETCONF的operations,比如configuration,state date,RPCs,以及notifications。它使得NETCONF的client和server之间能有完整的数据描述。
YANG建模得到的数据具备树形结构。其中每一个节点都有一个名字,都有一个值或者一些子节点。YANG为这些节点,以及节点之间的交互提供明确清晰的描述。
YANG使用modules和submodule进行数据建模。一个module能够从其他外部的modules中导入数据,也可以从submodules中包含数据。YANG定义的垂直结构可以扩展,使得一个module能够增加数据节点给另一个module。这种扩展是有条件的,只有特定条件满足,新的数据节点才会出现。
YANG模型还能描述数据之上增加的约束,基于垂直结构中其他节点的出现与否,值为多少等等来限制一些节点的出现与赋值。这些约束可以被client或者server强制执行。不过如果要使得内容有效,MUST 双方都要遵守特定的约定。
YANG定义了一系列的内建数据类型,也有定义新数据类型的类型命名机制。派生数据类型可以通过像range,pattern这样的声明限制其原生数据类型的取值范围,这样的声明在client或者server端都可以执行。它们还能为派生数据类型定义常用用法,比如定义一个string-based类型,包含主机名。
YANG允许对可重用的grouping中节点的定义。这些groupings中的实例能够通过特定的增强以满足特殊的需求。派生类型以及groupings能够定义在一个module或者submodule中,能够被本地,其他module/submodule导入和使用。
YANG的垂直数据结构包括了对list的定义。list中包含的每一项都有唯一的key以区分彼此。这样的lists有可能被用户自定义排序或者由系统进行默认排序。对于用户自定义排序的lists来说,operations是为了对列表项进行排序定义的。
YANG modules可以被转换为等价的XML格式,称为YANG Independent Notation(YIN)(Section 11),这使得相关的应用可以通过XML解析器或者XSLT脚本进行操作。从YANG到YIN的转换是无损的,因此也可以从YIN格式转换为YANG文件。
YANG试图在高层的数据建模和底层的比特数据编码(bits-on-the-wire encoding)之间追求平衡。YANG module的reader可以查看数据模型的高层视图,同时也能理解在NETCONF operations中,这些数据如何编码。
YANG是一种可扩展语言,允许标准制定者,设备商,以及个人定义新的声明(statement)。声明的语法使得这些扩展能够以一种自然的方式和标准的YANG 声明共存,同时使得reader能够有效得认知这些新扩展。
YANG resists the tendency to solve all possible problems, limiting the problem space to allow expression of NETCONF data models, not arbitrary XML documents or arbitrary data models. The data models described by YANG are designed to be easily operated upon by NETCONF operations.
为了扩大使用范围,YANG和SNMP协议的SMIv2(Structure of Management Information,RFC2578和RFC2579)保持了兼容。基于SMIv2的MIB modules能够以只读的方式自动转换为YANG modules。然而,YANG并不关心如何从YANG转换为SMIv2。
和NETCONF相似,YANG致力于和设备本身自带的管理机制进行平滑集成。这就使得需要利用设备当前的访问控制机制去保护/暴露数据模型的相应元素。
4.2 语言总览
本小节引入了YANG语言中的一些重要结构,这些在后面的章节中,对于理解语言细节能够提供一些帮助。这种方法解决了难以理解的相互联系的YANG概念和声明的复杂关系问题。关于YANG的声明(statement)和语法(syntax)的细节描述可见Section 7。
4.2.1 Modules和Submodules
一个module包含了三种类型的声明:
module-header statement(模块头声明) —— 描述了该module,给出了module相关的信息。
revision statement(版本声明)—— 描述了该module的历史信息。
definition statement(定义声明) —— 定义了数据模型的内容部分。
一个NETCONF Server可能会实现多个modules,拥有相同设备数据的多个视图,或者互不相交的多个子集的多个视图。这种情况下,Server可能会选择仅仅实现定义了所有可用数据的一个module。(A NETCONF server may implement a number of modules, allowing multiple views of the same data, or multiple views of disjoint subsections of the device’s data. Alternatively, the server may implement only one module that defines all available data.)
根据需求,一个module可以被分为多个submodules。而对外来说,依然是单个module,无论内部拥有多少个submodules。
“include”声明允许一个module或者submodule引用submodules中定义的数据;“import”声明允许引用其他modules中定义的数据。
4.2.2 数据建模基础(Data Modeling Basics)
YANG定义了四种用于数据建模的节点类型。在下面的每一个小节中,都有例子展示了YANG语法以及相应的NETCONF XML表达。
4.2.2.1 Leaf Nodes
一个leaf node包含了像integer或者string这样的简单数据。它有且仅有一个特定类型的值,并且没有子节点。
YANG 示例:
leaf host-name {
type string;
description “Hostname for this system”;
}
NETCONF XML 示例:
my.example.com
“leaf”的声明可以在Section 7.6 中找到。
4.2.2.2 Leaf-List Nodes
一个leaf-list是一系列的leaf nodes,每个leaf都有特定类型的值。
YANG 示例:
leaf-list domain-search {
type string;
description "List of domain names to search";
}
NETCONF XML 示例:
high.example.com
low.example.com
everywhere.example.com
1
2
3
4
“leaf-list”的声明可以在Section 7.7 中找到。
4.2.2.3 Container Nodes
一个container node用来将相关的节点归总到一个subtree中。一个container node只有子节点,没有值。一个container可能会包含任何类型的任何数量的子节点(包括leafs,lists,leaf-lists以及containers)。
YANG 示例:
container system {
container login {
leaf message {
type string;
description
“Message given at start of login session”;
}
}
}
1
2
3
4
5
6
7
8
9
10
NETCONF XML 示例:
Good morning
1
2
3
4
5
6
“container”的声明可以在Section 7.5 中找到。
4.2.2.4 List Nodes
一个List定义了一系列的列表项(list entries)。每个列表项都像是一个structure或者一个record instance,通过名为“key”的leaf的值唯一确定。一个list能定义多种key leafs,能够包含任意类型的任意数目的子节点(包括leafs,lists,containers)。
YANG 示例:
list user {
key “name”;
leaf name {
type string;
}
leaf full-name {
type string;
}
leaf class {
type string;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
NETCONF XML 示例:
glocks
Goldie Locks
intruder
snowey
Snow White
free-loader
rzell
Rapun Zell
tower
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
“list”的声明可以在Section 7.8 中找到。
4.2.2.5 Module示例
上述的那些声明组合起来能够定义一个简单的module:
// Contents of “acme-system.yang”
module acme-system {
namespace “http://acme.example.com/system“;
prefix “acme”;
organization "ACME Inc.";
contact "[email protected]";
description
"The module for entities implementing the ACME system.";
revision 2007-06-09 {
description "Initial revision.";
}
container system {
leaf host-name {
type string;
description "Hostname for this system";
}
leaf-list domain-search {
type string;
description "List of domain names to search";
}
container login {
leaf message {
type string;
description
"Message given at start of login session";
}
list user {
key "name";
leaf name {
type string;
}
leaf full-name {
type string;
}
leaf class {
type string;
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
4.2.3 State Data
YANG 能够通过“config”声明对state data和configuration data进行建模。当一个节点打上了“config false”的标签,它的子结构就打上了state data的标签,会通过NETCONF的操作,而不是操作。作为其父节点的containers,lists,以及key leafs也会上报,以给这个state data明确的上下文环境。
不清楚为什么还会有key leafs。
在下面的例子中,每个interface都定义了两个leafs,一个是configured speed(配置速率),另一个是observed speed(观察速率)。观察速率是不可配置的,所以它能通过NETCONF的操作获取,但是不能通过操作获取,也不能通过操作操作。
list interface {
key “name”;
leaf name {
type string;
}
leaf speed {
type enumeration {
enum 10m;
enum 100m;
enum auto;
}
}
leaf observed-speed {
type uint32;
config false;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
4.2.4 Built-in Types
和一些编程语言类似,YANG也有一系列的内置类型。下面的表格就总结了在Section 9描述的内置数据类型:
+———————+————————————-+
| Name | Description |
+———————+————————————-+
| binary | Any binary data |
| bits | A set of bits or flags |
| boolean | “true” or “false” |
| decimal64 | 64-bit signed decimal number |
| empty | A leaf that does not have any value |
| enumeration | Enumerated strings |
| identityref | A reference to an abstract identity |
| instance-identifier | References a data tree node |
| int8 | 8-bit signed integer |
| int16 | 16-bit signed integer |
| int32 | 32-bit signed integer |
| int64 | 64-bit signed integer |
| leafref | A reference to a leaf instance |
| string | Human-readable string |
| uint8 | 8-bit unsigned integer |
| uint16 | 16-bit unsigned integer |
| uint32 | 32-bit unsigned integer |
| uint64 | 64-bit unsigned integer |
| union | Choice of member types |
+———————+————————————-+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
“type”的声明可以在Section 7.4 中找到。
4.2.5 Derived Types(typedef)
YANG能够使用“typedef”声明从基本类型中定义派生类型。一个基本类型可以是内置类型或者派生类型。
YANG 示例:
typedef percent {
type uint8 {
range “0 .. 100”;
}
description “Percentage”;
}
leaf completed {
type percent;
}
1
2
3
4
5
6
7
8
9
10
11
NETCONF XML 示例:
20
1
2
“typedef”的声明可以在Section 7.3 中找到。
4.2.6 可重用的节点组(grouping)
可以使用“grouping”声明将一组节点放到可重用的集合中去。一个grouping定义了节点的集合,该集合可以使用“uses”声明实例化:
YANG 示例:
grouping target {
leaf address {
type inet:ip-address;
description “Target IP address”;
}
leaf port {
type inet:port-number;
description “Target port number”;
}
}
container peer {
container destination {
uses target;
}
}
1
2
3
4
5
6
NETCONF XML 示例:
1
2
3
4
5
6
7
grouping可以根据它被调用时候的用途进行优化,重写特定的声明来覆盖原来grouping的定义。在下面的例子中,description被重定义了:
container connection {
container source {
uses target {
refine “address” {
description “Source IP address”;
}
refine “port” {
description “Source port number”;
}
}
}
container destination {
uses target {
refine “address” {
description “Destination IP address”;
}
refine “port” {
description “Destination port number”;
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
“grouping”的声明可以在Section 7.11 中找到。
4.2.7 choice
YANG能够使用“choice”和“case”声明分离互不相容,不能同时出现的节点。“choice”声明包含了多个“case”声明,定义了不能同时出现的schema nodes的集合。每个“case”声明都可能包含多个节点,但是每个节点都应该只在一个“case”中出现。
当一个case元素被创建,其他所有cases的元素都会被隐式删除。设备要强制执行这个约束,以防止出现配置的不协调。
“choice”和“case”节点只会出现在schema tree中,不能出现在data tree或者NETCONF message。
YANG 示例:
container food {
choice snack {
case sports-arena {
leaf pretzel {
type empty;
}
leaf beer {
type empty;
}
}
case late-night {
leaf chocolate {
type enumeration {
enum dark;
enum milk;
enum first-available;
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
NETCONF XML 示例:
1
2
3
4
5
“choice”的声明可以在Section 7.9 中找到。
4.2.8 扩展数据模型(augment)
YANG允许一个模块将额外的节点插入到数据模型中,包括当前的module(以及它的submodule)或者一个外部的module。这一点是很有用的,比如对于设备商来说,需要在标准数据模型中插入设备商指定的参数。
“augment”声明定义了在数据模型树形结构中,新的节点插入的位置。“when”声明了新节点生效的时间。
YANG 示例:
augment /system/login/user {
when “class != ‘wheel’”;
leaf uid {
type uint16 {
range “1000 .. 30000”;
}
}
}
1
2
3
4
5
6
7
8
9
这个例子定义了一个“uid”的leaf node,该node仅在user的class不等于wheel的时候才有效。
如果一个module增强了另一个module,则数据的XML表示将会影响增强它的module的前缀。比如,如果上一个例子的augment是放在一个“other”前缀的module中,则其XML看起来应该是这样的:
NETCONF XML 示例:
alicew
Alice N. Wonderland
drop-out
1024
1
2
3
4
5
6
7
“augment”的声明可以在Section 7.15中找到。
4.2.9 RPC定义
YANG也能定义NETCONF中的RPCs。RPC中的operations’ name,输入参数,和输出参数都可以通过YANG的数据定义声明进行建模。
YANG 示例:
rpc activate-software-image {
input {
leaf image-name {
type string;
}
}
output {
leaf status {
type string;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
NETCONF XML 示例: