Yang语言.html
简介
YANG其实是一种数据建模语言,专门为netconf定制的一种模型配置语言,
NETCONF协议采用XML(可扩展标记语言)作为配置数据和协议消息的编码方式,用C/S和RPC方式来获取,更新或删除设备中的相应的部分或所有管理信息.
XML可以表达复杂的、具有内在逻辑关系的模型化的管理对象,大大提高了操作效率和对象标准化.XSD,Xpath, SOAP,XSLT等XML技术都可以应用到NETCONF协议中。
另外,协议采用SSHv2,SOAP,BEEP等传输方式,来提高传输的可靠性、安全性和交互性。
netconf的四层结构:
` +-------------+ +-----------------------------+
(4) | Content | | Configuration data |
+-------------+ +-----------------------------+
| |
+-------------+ +-----------------------------+
(3) | Operations | | <get-config>, <edit-config> |
+-------------+ +-----------------------------+
| |
+-------------+ +-----------------------------+
(2) | RPC | | <rpc>, <rpc-reply> |
+-------------+ +-----------------------------+
| |
+-------------+ +-----------------------------+
(1) | Transport | | BEEP, SSH, SSL, console |
| Protocol | | |
+-------------+ +-----------------------------+
“> +————-+ +—————————–+
(4) | Content | | Configuration data |
+————-+ +—————————–+
| |
+————-+ +—————————–+
(3) | Operations | | <get-config>, <edit-config> |
+————-+ +—————————–+
| |
+————-+ +—————————–+
(2) | RPC | | <rpc>, <rpc-reply> |
+————-+ +—————————–+
| |
+————-+ +—————————–+
(1) | Transport | | BEEP, SSH, SSL, console |
| Protocol | | |
+————-+ +—————————–+
YANG用来配置模型以及通过网络配置协议(NETCONF)、NETCONF远程调用和NETCONF通知来声明数据。YANG用来模拟业务操作和NETCONF的内容层。
官方的文档是:rfc6020_with_content,可以在网上下载看。
下面介绍一个yang语言的语法:
yang模型是用来表示配置模型的,有下面这些关键字:
1 module
一个module的定义包含几个部分:
第一部分是 namespace(命名空间),prefix(缩略语), import(引入的其他模块),include(包含哪些子模块submodule),
第二部分是这个module的历史信息以及相关描述,organization,contact,description,revision;其中organization,contact,description,revision这些可以不写,也可以编译通过。一般项目会要求写上revision修改记录。
第三部分是当前这个module里面的数据形式定义。
如:
module Equipment {
namespace "urn:com:params:xml:ns:yang:ran:Equipment";
prefix Equipment;
import ManagedElement{
prefix ME;
}
//revision这里没写。
augment "/ME:ManagedElement"{
container Equipment {
leaf name{
type string;
}
......
}
}
”> module Equipment {
namespace “urn:com:params:xml:ns:yang:ran:Equipment”;
prefix Equipment;
import ManagedElement{
prefix ME;
}
//revision这里没写。
augment "/ME:ManagedElement"{
container Equipment {
leaf name{
type string;
}
......
}
}
一个Module下面可以定义什么类型,我们可以查看协议rfc6020_with_content.pdf,如下这种:
7.1.1节定义的
` +--------------+---------+-------------+
| substatement | section | cardinality |
+--------------+---------+-------------+
| anyxml | 7.10 | 0..n |
| augment | 7.15 | 0..n |
| choice | 7.9 | 0..n |
| contact | 7.1.8 | 0..1 |
| container | 7.5 | 0..n |
| description | 7.19.3 | 0..1 |
| deviation | 7.18.3 | 0..n |
| extension | 7.17 | 0..n |
| feature | 7.18.1 | 0..n |
| grouping | 7.11 | 0..n |
| identity | 7.16 | 0..n |
| import | 7.1.5 | 0..n |
| include | 7.1.6 | 0..n |
| leaf | 7.6 | 0..n |
| leaf-list | 7.7 | 0..n |
| list | 7.8 | 0..n |
| namespace | 7.1.3 | 1 |
| notification | 7.14 | 0..n |
| organization | 7.1.7 | 0..1 |
| prefix | 7.1.4 | 1 |
| reference | 7.19.4 | 0..1 |
| revision | 7.1.9 | 0..n |
| rpc | 7.13 | 0..n |
| typedef | 7.3 | 0..n |
| uses | 7.12 | 0..n |
| yang-version | 7.1.2 | 0..1 |
+--------------+---------+-------------+
“> +————–+———+————-+
| substatement | section | cardinality |
+————–+———+————-+
| anyxml | 7.10 | 0..n |
| augment | 7.15 | 0..n |
| choice | 7.9 | 0..n |
| contact | 7.1.8 | 0..1 |
| container | 7.5 | 0..n |
| description | 7.19.3 | 0..1 |
| deviation | 7.18.3 | 0..n |
| extension | 7.17 | 0..n |
| feature | 7.18.1 | 0..n |
| grouping | 7.11 | 0..n |
| identity | 7.16 | 0..n |
| import | 7.1.5 | 0..n |
| include | 7.1.6 | 0..n |
| leaf | 7.6 | 0..n |
| leaf-list | 7.7 | 0..n |
| list | 7.8 | 0..n |
| namespace | 7.1.3 | 1 |
| notification | 7.14 | 0..n |
| organization | 7.1.7 | 0..1 |
| prefix | 7.1.4 | 1 |
| reference | 7.19.4 | 0..1 |
| revision | 7.1.9 | 0..n |
| rpc | 7.13 | 0..n |
| typedef | 7.3 | 0..n |
| uses | 7.12 | 0..n |
| yang-version | 7.1.2 | 0..1 |
+————–+———+————-+
意思就是说module下面支持从anyxml到yang-version这些关键字的定义。下面介绍各种关键字的时候不在重述这一部分。详细可查协议。
2 submodule
submodule是子模块的意思。submodule不用写module的第一部分,但是需要指定它的归属,如下
`submodule acme-types {
belongs-to "acme-system" {
prefix "acme";
}
import ietf-yang-types {
prefix "yang";
}
organization "ACME Inc.";
contact
"Joe L. User
ACME, Inc.
42 Anywhere Drive
Nowhere, CA 95134
USA
Phone: +1 800 555 0100
EMail: joe@acme.example.com";
description
"This submodule defines common ACME types.";
revision "2007-06-09" {
description "Initial revision.";
}
// definitions follows...
}
“>submodule acme-types {
belongs-to “acme-system” {
prefix “acme”;
}
import ietf-yang-types {
prefix “yang”;
}
organization “ACME Inc.”;
contact
“Joe L. User
ACME, Inc.
42 Anywhere Drive
Nowhere, CA 95134
USA
Phone: +1 800 555 0100
EMail: joe@acme.example.com”;
description
“This submodule defines common ACME types.”;
revision “2007-06-09” {
description “Initial revision.”;
}
// definitions follows…
}
并且一定要注意的是submodule归属于哪一个module,一定要在这个module里面用include包含这个submodule.
上面这个例子中,它是归属于acme-system,那么在acme-system里面必须要有这么一个引用:
“>module acme-system {
module acme-system {
namespace "urn:com:params:xml:ns:yang:ran:acme-system";
prefix acme;include acme-types {}
......
}
namespace “urn:com:params:xml:ns:yang:ran:acme-system”;
prefix acme;
include acme-types {}
……
}
3 leaf
最末端的叶子节点,它下面不包含任何节点或者一组节点,叶子节点里面就是类型定义、默认值、取值范围、是否是必填、是否是不可配等
leaf支持的定义
`+--------------+---------+-------------+
| substatement | section | cardinality |
+--------------+---------+-------------+
| config | 7.19.1 | 0..1 |
| default | 7.6.4 | 0..1 |
| description | 7.19.3 | 0..1 |
| if-feature | 7.18.2 | 0..n |
| mandatory | 7.6.5 | 0..1 |
| must | 7.5.3 | 0..n |
| reference | 7.19.4 | 0..1 |
| status | 7.19.2 | 0..1 |
| type | 7.6.3 | 1 |
| units | 7.3.3 | 0..1 |
| when | 7.19.5 | 0..1 |
+--------------+---------+-------------+
“>+————–+———+————-+
| substatement | section | cardinality |
+————–+———+————-+
| config | 7.19.1 | 0..1 |
| default | 7.6.4 | 0..1 |
| description | 7.19.3 | 0..1 |
| if-feature | 7.18.2 | 0..n |
| mandatory | 7.6.5 | 0..1 |
| must | 7.5.3 | 0..n |
| reference | 7.19.4 | 0..1 |
| status | 7.19.2 | 0..1 |
| type | 7.6.3 | 1 |
| units | 7.3.3 | 0..1 |
| when | 7.19.5 | 0..1 |
+————–+———+————-+
下面举个例子:
` leaf Param {
type string {
length "0..34";
}
mandatory true;//必须配置的
default 0;
units s;//单位
description "Param";
}
“> leaf Param {
type string {
length “0..34”;
}
mandatory true;//必须配置的
default 0;
units s;//单位
description “Param”;
}
上面是字符类型的
`leaf Param {
type int32 {
length "0..65535";
}
default 0;
description "Param";
}
“>leaf Param {
type int32 {
length “0..65535”;
}
default 0;
description “Param”;
}
上面是数值类型的,其中int4的范围是-16到15,int8的范围是-256到255,以此类推。
int是无符号的,uint是指正整型,uint4的范围是0..16,以此类推。
`leaf holdoverSwitch {
type enumeration {
enum Disable;
enum Enable;
}
default Enable;
description "Holdover Time-Out Switch";
}
“>leaf holdoverSwitch {
type enumeration {
enum Disable;
enum Enable;
}
default Enable;
description “Holdover Time-Out Switch”;
}
这种是枚举类型的,其中枚举类型表示的时候都是显示值,其中内存值如果没有特别注明就是从0开始,如果我们的枚举不是从0开始顺序枚举的,需要另外加上value值,如下
`leaf radioMode {
type enumeration {
enum LTE-FDD { value 16; }
enum LTE-TDD { value 32; }
}
default LTE-TDD;
description "Cell type";
}
“>leaf radioMode {
type enumeration {
enum LTE-FDD { value 16; }
enum LTE-TDD { value 32; }
}
default LTE-TDD;
description “Cell type”;
}
另外枚举类型需要注意:enum后面的这个显示的字符串,不支持中文,并且如果字符串中间有空格,需要用引号引起来,比如:
`type enumeration {
enum "LTE FDD" { value 16; }
enum "LTE TDD" { value 32; }
}
“>type enumeration {
enum “LTE FDD” { value 16; }
enum “LTE TDD” { value 32; }
}
leaf解析成xml的时候是作为一个元素来解析的
比如上面的最后一个例子对应的xml数据就是
`<radioMode>16</radioMode>
“><radioMode>16</radioMode>
leaf下面还有union和choice.
leaf的默认值的处理要特别注意:如果用get-config操作获取数据的时候,如果当前叶子节点没有数据,但是存在默认值,系统会把默认值返回。这和之前的网管是不一样的。
reference是使用一个字符串定义引用外部文件的连接,或提供与此相关的附加信息的文档定义;
config是定义该节点是否可配,默认是可配的,如果要定义成不可配,需要加上config false;
union是说如果节点定义是union的,表示这个节点的类型是它下面的类型中的一个,这里有个例子:
`typedef ip-address {
type union {
type ipv4-address;
type ipv6-address;
}
description
"The ip-address type represents an IP address and is IP version neutral.";
reference
"RFC 4007: IPv6 Scoped Address Architecture";
}
“>typedef ip-address {
type union {
type ipv4-address;
type ipv6-address;
}
description
“The ip-address type represents an IP address and is IP version neutral.”;
reference
“RFC 4007: IPv6 Scoped Address Architecture”;
}
if-feature是和feature结合使用的,是说有些特征有条件的存在于模型上。yang模型支持设备提供不同的能力和角色。
举个协议上的例子:
`module syslog {
...
feature local-storage {
description
"This feature means the device supports local storage that can be used to store syslog messages.";
}
container syslog {
leaf local-storage-limit {
if-feature local-storage;
type uint64;
units "kilobyte";
config false;
description
"The amount of local storage that can be used to hold syslog messages.";
}
}
}
“>module syslog {
…
feature local-storage {
description
“This feature means the device supports local storage that can be used to store syslog messages.”;
}
container syslog {
leaf local-storage-limit {
if-feature local-storage;
type uint64;
units “kilobyte”;
config false;
description
“The amount of local storage that can be used to hold syslog messages.”;
}
}
}
意思就是说local-storage这个特征,是在下面有if-feature指向了这个feature的时候才会生效。如果module里面没有if-feature local-storage,那么local-storage这个特征将不会被使用。
must是用来写简单约束的。
must在一些关键字下面的不支持的,用之前要看一下协议
` leaf intraA3Hysteresis4Cate0 {
type decimal64 {
fraction-digits 1;
range "0..15";
}
default 1.5;
units dB;
description "This parameter indicates the hysteresis used for judging event during handover.";
}
must " intraA3Hysteresis4Cate0*10 mod 5 = 0 " {
error-message "intraA3Hysteresis4Cate0 must be in [0..15] step 0.5";
}
“> leaf intraA3Hysteresis4Cate0 {
type decimal64 {
fraction-digits 1;
range “0..15”;
}
default 1.5;
units dB;
description “This parameter indicates the hysteresis used for judging event during handover.”;
}
must ” intraA3Hysteresis4Cate0*10 mod 5 = 0 ” {
error-message “intraA3Hysteresis4Cate0 must be in [0..15] step 0.5”;
}
这个例子就是定义步长的。
还有类似这种的:
`leaf interCarriFreq {
type decimal64 {
fraction-digits 1;
range "0..6000";
}
mandatory true;
units MHz;
description "This parameter is used to configure the frequency of intra-LTE inter-frequency.";
}
must "freqBandInd != 1 or " +
"(freqBandInd = 1 and interCarriFreq >= 2110 and interCarriFreq <=2170)" {
error-message "freqBandInd=1, interCarriFreq must be [2110..2170]";
}
“>leaf interCarriFreq {
type decimal64 {
fraction-digits 1;
range “0..6000”;
}
mandatory true;
units MHz;
description “This parameter is used to configure the frequency of intra-LTE inter-frequency.”;
}
must “freqBandInd != 1 or ” +
“(freqBandInd = 1 and interCarriFreq >= 2110 and interCarriFreq <=2170)” {
error-message “freqBandInd=1, interCarriFreq must be [2110..2170]”;
}
must 后面有引号引起来的就是条件部分,然后是大括号,里面是如果不符合约束,那么错误信息的定义。
mandatory这个关键字是定义该节点是否必须配置,默认是false。如果定义成mandatory true,那么就不能用default。这点需要注意。
我理解这里的意思是如果这个节点必须配置,那么默认值就会被忽略。并且在模式树上,这个节点是一定存在的。
when的用法在另一篇文档中有说明。
别的类型在这里不详细说明。
4 leaf-list
表示数组的意思,但是和我们理解的数组不太一样,有一个很明显不同,yang定义的这个数组当中不允许每个元素的值相同。
例子:
`leaf-list blackListIP {
max-elements 20;
type mocommon:ip-address;
description "IP Blacklist";
}
“>leaf-list blackListIP {
max-elements 20;
type mocommon:ip-address;
description “IP Blacklist”;
}
这个里面max-elements是指这个数组的最大元素数,如果需要定义这个数组是必须配置的,那么需要在定义一个:
`min-elements 1;
“>min-elements 1;
意思就是这个数组最低要配置一个元素。
leaf-list支持下面这些
`+--------------+---------+-------------+
| substatement | section | cardinality |
+--------------+---------+-------------+
| config | 7.19.1 | 0..1 |
| description | 7.19.3 | 0..1 |
| if-feature | 7.18.2 | 0..n |
| max-elements | 7.7.4 | 0..1 |
| min-elements | 7.7.3 | 0..1 |
| must | 7.5.3 | 0..n |
| ordered-by | 7.7.5 | 0..1 |
| reference | 7.19.4 | 0..1 |
| status | 7.19.2 | 0..1 |
| type | 7.4 | 1 |
| units | 7.3.3 | 0..1 |
| when | 7.19.5 | 0..1 |
+--------------+---------+-------------+
“>+————–+———+————-+
| substatement | section | cardinality |
+————–+———+————-+
| config | 7.19.1 | 0..1 |
| description | 7.19.3 | 0..1 |
| if-feature | 7.18.2 | 0..n |
| max-elements | 7.7.4 | 0..1 |
| min-elements | 7.7.3 | 0..1 |
| must | 7.5.3 | 0..n |
| ordered-by | 7.7.5 | 0..1 |
| reference | 7.19.4 | 0..1 |
| status | 7.19.2 | 0..1 |
| type | 7.4 | 1 |
| units | 7.3.3 | 0..1 |
| when | 7.19.5 | 0..1 |
+————–+———+————-+
常用的上面已经讲过,这里特别说一下ordered-by。这个是排序的意思。如果不定义,那么netconf将采用默认的方式进行排序,但这里也提供给用户定义,可以指定有系统排序还是用户排序。假设当前这个数组排序有特别的意思,那么用户可以指定排序方式。
协议中有例子,谁有兴趣可以详细研究一下
5 list
list表示一组节点的集合。
list下面包含这些关键字:
`+--------------+---------+-------------+
| substatement | section | cardinality |
+--------------+---------+-------------+
| anyxml | 7.10 | 0..n |
| choice | 7.9 | 0..n |
| config | 7.19.1 | 0..1 |
| container | 7.5 | 0..n |
| description | 7.19.3 | 0..1 |
| grouping | 7.11 | 0..n |
| if-feature | 7.18.2 | 0..n |
| key | 7.8.2 | 0..1 |
| leaf | 7.6 | 0..n |
| leaf-list | 7.7 | 0..n |
| list | 7.8 | 0..n |
| max-elements | 7.7.4 | 0..1 |
| min-elements | 7.7.3 | 0..1 |
| must | 7.5.3 | 0..n |
| ordered-by | 7.7.5 | 0..1 |
| reference | 7.19.4 | 0..1 |
| status | 7.19.2 | 0..1 |
| typedef | 7.3 | 0..n |
| unique | 7.8.3 | 0..n |
| uses | 7.12 | 0..n |
| when | 7.19.5 | 0..1 |
+--------------+---------+-------------+
“>+————–+———+————-+
| substatement | section | cardinality |
+————–+———+————-+
| anyxml | 7.10 | 0..n |
| choice | 7.9 | 0..n |
| config | 7.19.1 | 0..1 |
| container | 7.5 | 0..n |
| description | 7.19.3 | 0..1 |
| grouping | 7.11 | 0..n |
| if-feature | 7.18.2 | 0..n |
| key | 7.8.2 | 0..1 |
| leaf | 7.6 | 0..n |
| leaf-list | 7.7 | 0..n |
| list | 7.8 | 0..n |
| max-elements | 7.7.4 | 0..1 |
| min-elements | 7.7.3 | 0..1 |
| must | 7.5.3 | 0..n |
| ordered-by | 7.7.5 | 0..1 |
| reference | 7.19.4 | 0..1 |
| status | 7.19.2 | 0..1 |
| typedef | 7.3 | 0..n |
| unique | 7.8.3 | 0..n |
| uses | 7.12 | 0..n |
| when | 7.19.5 | 0..1 |
+————–+———+————-+
例子:
`list VMDevice {
key serialInfo;
leaf serialInfo {
type string;
}
leaf name {
type string;
}
}
“>list VMDevice {
key serialInfo;
leaf serialInfo {
type string;
}
leaf name {
type string;
}
}
一个list中必须存在主键值,即必须定义Key。
这个其实可以理解,因为yang当中的所有数组,它都认为数组内部的元素是唯一的,不允许相同的情况存在。
数据是这么构建的:这个list的上级节点在这里不进行描述了
`<VMDevice>
<serialInfo>1</serialInfo>
<name>device1</name>
</VMDevice>
<VMDevice>
<serialInfo>2</serialInfo>
<name>device2</name>
</VMDevice>
...
“><VMDevice>
<serialInfo>1</serialInfo>
<name>device1</name>
</VMDevice>
<VMDevice>
<serialInfo>2</serialInfo>
<name>device2</name>
</VMDevice>
…
其中需要注意的是,这个list的主键是serialInfo,那么如果数据当中serialInfo这个的值有相同的情况,那么yang模型会不认,要不然是报错处理,要不然就是覆盖处理。
6 container
container是单例。
”>container ManagedElement {
container ManagedElement {
leaf ManagedElementId {
type int32;
mandatory true;
}leaf meId { type int32; mandatory true; } leaf locationName { type string; mandatory true; }
}
leaf ManagedElementId {
type int32;
mandatory true;
}
leaf meId {
type int32;
mandatory true;
}
leaf locationName {
type string;
mandatory true;
}
}
container和list是可以直接挂在配置模型树上的。
container有两个模式,一个是默认值模式,一个是presence模式。像上面的例子就是默认值模式,也就是说container的默认情况就是这种。这种节点挂在配置树上之后,如果我们用get-config命令进行获取的时候,如果这个container没有配置数据,那么系统会返回给客户端所有的默认值。——这点和我们以前配置的理解是不一样的
如果我们配置的有数据,那么可以将配置的数据和默认值一并返回。
那么presence定义的情况是怎么样的呢?如果是presence container,并且用户并没有配置这个数据,那么从客户端发命令get-config的时候,并不会返回任何值;如果用户有配置数据,那么再执行命令get-config的时候,系统会返回用户配置的数据以及没有配但是有默认值的数据。
详细的测试过程可以见另外一个文档《prenese关键字的分析》。
上面这个例子的数据格式是:
`<ManagedElement>
<ManagedElementId>1</ManagedElementId>
<meId>1</meId>
<locationName></locationName>
</ManagedElement>
“><ManagedElement>
<ManagedElementId>1</ManagedElementId>
<meId>1</meId>
<locationName></locationName>
</ManagedElement>
当然这个数据只能是一条。
7 typedef
这个就是自定义类型。
yang模型有一些常用的类型,比如int,string,enumation,decimal64(浮点类型)等,如果一个定义在多处都用到了,那么我们不用写很多次,定义成一个类型,引用它就行了
”>typedef time {
typedef time {
type string {
length "1..20";
pattern '\d{1,2}:\d{1,2}';
}
}list SonPolicyAnrTDD {
description "SON ANR Policy";
max-elements 64;
key "sonPolicyId";leaf anrAppointRptStartTime { type time; default 00:00; description ""; }
}
type string {
length “1..20”;
pattern ‘\d{1,2}:\d{1,2}’;
}
}
list SonPolicyAnrTDD {
description “SON ANR Policy”;
max-elements 64;
key “sonPolicyId”;
leaf anrAppointRptStartTime {
type time;
default 00:00;
description "";
}
}
也可以引用别的文件模型里面的type,只用引用这个module就可以用了
”>module EUtranCellTDD {
module EUtranCellTDD {
namespace "urn:com:params:xml:ns:yang:ran:4g:eutrancelltdd";
prefix "eutrancelltdd";import MoCommon { prefix "mocommon"; } list EUtranCellTDD { description "E-UTRAN TDD Cell"; max-elements 36; key "cellLocalId"; leaf EUtranCellTDDId { type mocommon:Mo_Id; mandatory true; } }
}
namespace “urn:com:params:xml:ns:yang:ran:4g:eutrancelltdd”;
prefix “eutrancelltdd”;
import MoCommon {
prefix "mocommon";
}
list EUtranCellTDD {
description "E-UTRAN TDD Cell";
max-elements 36;
key "cellLocalId";
leaf EUtranCellTDDId {
type mocommon:Mo_Id;
mandatory true;
}
}
}
8 grouping
grouping就是用来定义重复用的一组节点。
可以在一个module里面用,也可以引用别的module里面的grouping
grouping不是一个数据定义状态。不能在配置树上呈现。
”>module SonCommon {
module SonCommon {
namespace "urn:com:params:xml:ns:yang:ran:4g:soncommon";
prefix "soncommon";grouping son-policy { leaf sonFuncId { type int32 { range "0..255"; } default 43; description "Service Type"; } leaf reportSwitch { type enumeration { enum Close; enum Open; } default Close; description "Monitor Message Report Switch"; } }
}
module SonPolicyPciTDD {
namespace "urn:com:params:xml:ns:yang:ran:4g:sonpolicypcitdd";
prefix "sonpolicypcitdd";import MoCommon { prefix "mocommon"; } import SonCommon { prefix "soncommon"; } list SonPolicyPciTDD { description "SON PCI Policy"; key "sonPolicyId"; leaf SonPolicyPciTDDId { type mocommon:Mo_Id; } leaf description { type mocommon:Mo_description; } leaf sonPolicyId { type int32 { range "47000..47999"; } //default 47000; description "Policy ID"; } uses soncommon:son-policy { refine sonFuncId { default 47; } } }
}
namespace “urn:com:params:xml:ns:yang:ran:4g:soncommon”;
prefix “soncommon”;
grouping son-policy {
leaf sonFuncId {
type int32 {
range "0..255";
}
default 43;
description "Service Type";
}
leaf reportSwitch {
type enumeration {
enum Close;
enum Open;
}
default Close;
description "Monitor Message Report Switch";
}
}
}
module SonPolicyPciTDD {
namespace “urn:com:params:xml:ns:yang:ran:4g:sonpolicypcitdd”;
prefix “sonpolicypcitdd”;
import MoCommon {
prefix "mocommon";
}
import SonCommon {
prefix "soncommon";
}
list SonPolicyPciTDD {
description "SON PCI Policy";
key "sonPolicyId";
leaf SonPolicyPciTDDId {
type mocommon:Mo_Id;
}
leaf description {
type mocommon:Mo_description;
}
leaf sonPolicyId {
type int32 {
range "47000..47999";
}
//default 47000;
description
"Policy ID";
}
uses soncommon:son-policy {
refine sonFuncId {
default 47;
}
}
}
}
如果要用的grouping和之前定义的完全一样,像上述例子,那么直接这样用就行了:
uses soncommon:son-policy;
但是如果要用的grouping和之前定义过的有一些不同,我们也可以用,不过在差异部分重新定义一下就可以了,像上面的例子 refine一样,是默认值不一样,那么重新覆盖上一个就行了。
9 augment
augment是定义往配置树上额外挂载节点,也可表示父子归属关系。
”>module ENBFunctionTDD {
module ENBFunctionTDD {
namespace "urn:com:params:xml:ns:yang:ran:4g:enbfunctiontdd";
prefix "enbfunctiontdd";import MoCommon { prefix "mocommon"; } import ManagedElement { prefix "ME"; } import Equipment { prefix "Equipment"; } augment "/ME:ManagedElement" { container ENBFunctionTDD { presence ENBFunctionTDD; leaf ENBFunctionTDDId { type uint32 { range "0..1048575"; } mandatory true; description "RDN"; } }
}
namespace “urn:com:params:xml:ns:yang:ran:4g:enbfunctiontdd”;
prefix “enbfunctiontdd”;
import MoCommon {
prefix "mocommon";
}
import ManagedElement {
prefix "ME";
}
import Equipment {
prefix "Equipment";
}
augment "/ME:ManagedElement" {
container ENBFunctionTDD {
presence ENBFunctionTDD;
leaf ENBFunctionTDDId {
type uint32 {
range "0..1048575";
}
mandatory true;
description "RDN";
}
}
}
这个例子是说ENBFunctionTDD这个节点是挂载在ManagedElement下的,相当于ManagedElement的孩子。
像这种的数据是下面这样的:
`<ManagedElement xmlns="urn:com:params:xml:ns:yang:ran:ManagedElement">
<locationName>2</locationName>
<Id>1</Id>
<ENBFunctionTDD xmlns="urn:com:params:xml:ns:yang:ran:ENBFunctionTDD">
<EUtranCellTDD xmlns="urn:com:params:xml:ns:yang:ran:ENBFunctionTDD">
<mcc>3</mcc>
</EUtranCellTDD>
</ENBFunctionTDD>
</ManagedElement>
“><ManagedElement xmlns=”urn:com:params:xml:ns:yang:ran:ManagedElement”>
<locationName>2</locationName>
<Id>1</Id>
<ENBFunctionTDD xmlns=”urn:com:params:xml:ns:yang:ran:ENBFunctionTDD”>
<EUtranCellTDD xmlns=”urn:com:params:xml:ns:yang:ran:ENBFunctionTDD”>
<mcc>3</mcc>
</EUtranCellTDD>
</ENBFunctionTDD>
</ManagedElement>
每个module都需要填写上namespace
augment挂载的container,不允许这个container下面的节点定义成mandatory.
但是如果augment挂载的container定义成了prenese,那么下面的节点可以定义成mandatory.
10 rpc
协议中一个很典型的例子:
`rpc activate-software-image {
input {
leaf image-name {
type string;
}
}
output {
leaf status {
type string;
}
}
}
“>rpc activate-software-image {
input {
leaf image-name {
type string;
}
}
output {
leaf status {
type string;
}
}
}
对应的xml就是:
`<rpc message-id="101"
xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<activate-software-image xmlns="http://acme.example.com/system">
<image-name>acmefw-2.3</image-name>
</activate-software-image>
</rpc>
<rpc-reply message-id="101"
xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<status xmlns="http://acme.example.com/system">
The image acmefw-2.3 is being installed.
</status>
</rpc-reply>
“><rpc message-id=”101”
xmlns=”urn:ietf:params:xml:ns:netconf:base:1.0”>
<activate-software-image xmlns=”http://acme.example.com/system”>
<image-name>acmefw-2.3</image-name>
</activate-software-image>
</rpc>
<rpc-reply message-id=”101”
xmlns=”urn:ietf:params:xml:ns:netconf:base:1.0”>
<status xmlns=”http://acme.example.com/system”>
The image acmefw-2.3 is being installed.
</status>
</rpc-reply>
特别注意,写数据的时候,这一行的定义必不可少。下面才是rpc本身的信息
11 notification
notification就是通知消息,
协议上一个例子是:
`notification link-failure {
description "A link failure has been detected";
leaf if-name {
type leafref {
path "/interface/name";
}
}
leaf if-admin-status {
type admin-status;
}
leaf if-oper-status {
type oper-status;
}
}
“>notification link-failure {
description “A link failure has been detected”;
leaf if-name {
type leafref {
path “/interface/name”;
}
}
leaf if-admin-status {
type admin-status;
}
leaf if-oper-status {
type oper-status;
}
}
对应上报的xml就是这样的:
`<notification xmlns="urn:ietf:params:netconf:capability:notification:1.0">
<eventTime>2007-09-01T10:00:00Z</eventTime>
<link-failure xmlns="http://acme.example.com/system">
<if-name>so-1/2/3.0</if-name>
<if-admin-status>up</if-admin-status>
<if-oper-status>down</if-oper-status>
</link-failure>
</notification>
“><notification xmlns=”urn:ietf:params:netconf:capability:notification:1.0”>
<eventTime>2007-09-01T10:00:00Z</eventTime>
<link-failure xmlns=”http://acme.example.com/system”>
<if-name>so-1/2/3.0</if-name>
<if-admin-status>up</if-admin-status>
<if-oper-status>down</if-oper-status>
</link-failure>
</notification>
同样的这一行必不可少。
12 yang中的path
特别说明一下:在我们mo模型里面,有很多引用字段,那么yang语法中怎么表示呢?
yang语法也是支持的,见下面:
`leaf refSignalResCfgTDD {
type leafref {
path "/ME:ManagedElement/enbfunctiontdd:ENBFunctionTDD/signalrescfgtdd:SignalResCfgTDD/signalrescfgtdd:sigResIdx";
}
description "";
}
“>leaf refSignalResCfgTDD {
type leafref {
path “/ME:ManagedElement/enbfunctiontdd:ENBFunctionTDD/signalrescfgtdd:SignalResCfgTDD/signalrescfgtdd:sigResIdx”;
}
description “”;
}
上面这个path的意思就是说refSignalResCfgTDD指向的是ManagedElement-ENBFunctionTDD-signalrescfgtdd-sigResIdx的值。
有一点和现在网管不同的是,yang模型必须指向一个叶子节点,并且存储的也是这个节点的值,而不会把路径都记录下来,类似MOI一样。