精华内容
下载资源
问答
  • 企业数据标准规划、建设和应用

    千次阅读 2016-11-29 10:32:21
    今天我分享的内容,整体包括三个部分:第一部分主要介绍为什么要建标准,建设数据标准带来价值是什么;什么是数据标准,业界数据标准体系架构,数据标准具体表现形式是什么样...一、企业数据建设现状长久以来,大多...

    今天我分享的内容,整体包括三个部分:

    第一部分主要介绍为什么要建标准,建设数据标准带来价值是什么;什么是数据标准,业界数据标准体系架构,数据标准具体表现形式是什么样的,数据标准包含内容有哪些;
    
    第二部分结合我们数据标准实施经验,介绍标准如何建立、落地、维护的整个流程;并介绍几个标准落地的几个关键点;
    
    第三部分给出了一个案例,描述典型的数据标准实施路径,供参考。
    

    一、企业数据建设现状

    图片描述

    长久以来,大多数的系统都是在某些业务需求的基础上建立,没有考虑与其他系统的功能重复和数据重复,数据一致性和可用性的矛盾突出。由于缺乏这种对数据整体设计考虑,造成多种数据问题:

    数据需求缺乏规范,造成数据对象多份存储,存储结构各异,严重影响数据共享。
    

    例如:某金融公司客户信息存在于财务和产品两个系统中,由于建设时期和团队不同,其中对客户代码长度的定义不一致,财务系统中定义为4位,产品系统中定义为6位,导致同样的数据要素在财务系统和客户系统中标准不一致,造成同一客户财务和产品信息不能很好打通。

    数据标准依据各异,造成统计口径无法匹配。
    

    例如:某金融公司原有系统,业务类型采用业界标准包括资产收购与经营、投资、融资顾问等;由于公司发展,开展了新的业务,因此后来的系统中采用公司新标准,出现了商业收购、阶段性投融资等业务类型。结果新旧系统在业务类型上不一致,业务人员要人为的做关联。

    业务口径不统一,造成沟通困难,发生歧义。
    

    例如:某业务部门,需要财务部门提供一份月报表,由于对“余额”一词有不同的理解,一个认为是“期初余额”,而另一个认为是“期末余额”,造成统计结果大相径庭。经过多次沟通,才达到满意效果。

    数据缺乏标准造成的问题还有很多,总的来说,需要从数据对象、代码、业务指标等多方面实现标准化,才能从根本上减少这些数据问题。那数据标准能给我们带来什么?

    图片描述

    标准可以在业务、技术、管理多个方面给我们提供支撑。

    业务方面:

    提升业务规范性
    

    通过标准可以明确很多数据业务含义,使得不同业务部门之间,以及业务与技术之间沟通更加通畅,避免歧义。

    例如通过客户数据标准,我们在讲客户的时候,大家理解的是一致的,只有办了银行卡的人,才是银行客户。而不会再有认为在网站注册、或者通过本行转账的人都是客户的理解。

    提升数据对业务分析支持度
    

    通过数据标准,可以明确的把某个数据主题(例如客户)信息分为多类,例如基本信息、联系信息、财务信息等,为多维度分析和深度挖掘提供依据。

    通过数据标准,实现数据信息统一一致,使得数据更容易在各业务部门之间流转。
    

    技术方面:

    首先,相同结构的数据,才更容易实现共享和交换;因此公司内部标准促进数据在企业内部流转,行业标准促进数据在企业之间流转;
    
    其次,相同的数据标准,减少大量的转换、清洗工作,极大的提升数据处理效率;数据处理过程中也会减少出差几率,提升问题质量。
    

    管理方面:

    数据标准更多的是能提供完整、及时、准确、高质量的数据,为决策支持、精细化管理等提供支撑。
    

    那么,到底什么是数据标准呢?

    图片描述

    一般我们直观认为数据标准就是几个文档,描述了一些规范和要求,需要大家去遵守。

    更严谨一点定义,数据标准是为了使企业内外部使用和交换的数据是一致和准确的,经协商一致制定并由相关主管机构批准,共同使用和重复使用的一种规范性文件。

    而我们认为数据标准又不仅仅是一套规范,而是一套由管理规范、管控流程、技术工具共同组成的体系,是通过这套体系逐步实现信息标准化的过程。数据标准化是通过一整套的数据规范、管控流程和技术工具来确保的各种重要信息,例如产品、客户、机构、账户等在全公司内外的使用和交换都是一致、准确的过程。

    另外,数据标准也不仅仅是技术或者业务一个部门的事情,它是在数据层面上对重要业务主题的统一规范,也是业务规范在数据层面上的实现。数据标准实施依赖于业务部门之间的共识,以及业务和技术之间的配合。

    那么业界常用的数据标准体系是什么样的呢?标准长什么样,包含哪些内容?下面我会对数据标准的分类和参考体系、内容和形式做一下简单介绍,可以做一个直观的理解。

    图片描述

    首先,数据标准根据不同的数据域分为基础、分析类和专有类三类

    基础类数标是企业日常业务开展过程中所产生的具有共同业务特征的基础性数据,如客户、产品、财务等;
    
    分析类数标是为满足公司内部管理需要及外部监管要求,在基础性数据基础上按一定统计、分析规则加工后的数据;
    
    专有类数标是公司架构下子公司在业务经营及管理分析中所涉及的特有数据。
    

    其中,针对基础类数标,可以看一下金融行业经常用的数据标准十大主题模型。该模型是以主题组织数据,包括客户、资产、机构、产品等主题。

    那么针对某个数据主题,数据标准到底由那几部分组成呢?

    图片描述

    一般数据标准会包括:主题定义、信息项、标准代码三个文档,其中:

    标准主题定义文档:主要是记录数据标准的定义、分类,用于规范和识别数据的主题归属;
    
    标准信息项文档:记录数据主题的信息项业务属性(分类、业务含义、业务逻辑)和技术属性(类型、长度、默认规则);
    
    标准代码文档:记录信息项固定码值的编码、分类、使用规则等。
    

    信息项文档是数据标准的核心。内容包括分类、业务描述和技术描述,一般由信息大类、信息小类、信息项、信息项描述、信息类别、长度共6项组成。当然这些内容也可以调整,例如信息大类、小类,可以合并,或者拆除更多层级。

    信息大、小类是对信息项的常规分类,例如:例如客户信息大类包括基本信息、联系信息、关联信息、财务信息、风险信息、评价信息、往来信息七大类;信息小类,包括:客户编号、名称、证件、地址、评级信息、模型评分、等级、开办业务等;

    信息项是用来描述一个事物的最基本元素。表示一个事物的识别、限制、数量、分类、状态,或者事物间的关系,例如客户信息的名称、年龄、性别等;

    信息项描述是描写或者规范信息项的具体业务描述及界定;

    信息类别是根据业务需求,定义相应的信息项在数据库中所需要的技术格式。例如:编号、标志、代码、金额、日期、数值、文本等;

    长度是信息项的数据长度,供各系统建设参考使用。

    二、如何建设数据标准

    图片描述

    一般数据包标准包括制定、落地、维护等过程。其中制定过程包括规划、调研、设计;落地过程通过映射、标准执行等实现;维护过程保证了数据标准的持续更新。

    1、首先,在标准制定过程中的第一个阶段,标准规划阶段,要根据业界经验和企业实际情况确定实施范围,并根据优先级和难易度制定计划。

    例如,在金融行业,以金融行业十大主题为依据开展,通过业务了解,确定产品、客户、财务等几个主题是关键主题,其他主题业务关联性很弱;因此,确定实施范围,并根据紧迫度、资金等因此确定了实施计划,分多期建立。
    

    2、接下来,在调研阶段,通过制定调查问卷、安排现场访谈、收集文档资料等手段,针对各个业务系统以及应用系统进行调研,了解跟标准相关的内容,包括现有定义、使用习惯、数据分布、数据流向、业务规则、服务部门等,形成调研报告,分析问题,并讨论解决方案。

    实施过程中,如果多个部门不清楚项目意义和项目目标,首先需要对各部门做项目宣讲,让他们有充分了解。
    
    然后,通过调研问卷方式进行初步了解沟通,同期开始大批量研究企业现有的文档了解业务和数据集。
    
    最后,通过当面访谈深入了解信息,并讨论问题与解决方案。最终通过开评审会方式确定解决方案,并给出分析报告。
    

    3、有了素材,接下来就是开始标准设计工作。

    在这个阶段主要是在方法论指导下,完成数据标准设计和定义工作,包括数据业务描述定义(业务属性)、类型长度定义(技术属性)、其他标准信息定义。
    
    设计出定义与分类、信息项、标准码等文档,并通过各部门的评审验证。最终达成一致,形成企业级标准。
    

    到此,标准制定工作完毕。

    4、接下来主要是标准如何落地工作。把已定义的数据标准与业务系统、业务应用进行映射,标明标准和现状的关系以及可能影响到的应用。

    标准落地一般通过两种方式:
    
    1)新系统建设,直接参考数据标准;
    
    2)旧系统通过标准映射,实现数据关系转换,以及指导后续数据平台建设。
    

    5、做完数据标准映射,接下了就是标准落地执行。

    这个过程一般需要借助专业的工具实现标准落地检查。标准执行一般有两个过程
    
    1)第一步分析出来现有问题,例如数据缺失、数据不一致等;
    
    2)第二步修正,例如补录数据、修改系统、新建系统等。
    
    通过这些措施,逐步规范数据建设过程,实现数据标准的落地。
    

    6、数据标准也不是一成不变的,随着业务发展,有些标准需要不断的修订和完善。因此数据标准还有一个关键的管理环节,那就是需要能持续维护改进。

    在数据标准维护阶段,需要有相应的需求收集、需求评审、变更评审、发布等多个步骤,并能对所有的修订做版本管理,以方便将来问题查找。
    

    以上讲了数据标准管理的全过程,接下来我对数据标准落地的几个关键点做一个简单介绍。

    图片描述

    第一条关键点:数据标准应该只管理核心数据定义

    首先,标准不是模型,标准是可落地的核心元素。
    
    企业实际数据模型中有上万个字段,有些模型还会经常变换更新,如果把这些信息全部纳入到标准体系中,并且和数据标准建立映射,管理起来非常困难,很难真正实现落地。
    
    因此要实现数据标准落地,不能一味追求大而全,更多的是应该关注在众多数据中挑选出的核心数据,只管理这些核心数据定义,依照核心数据建立标准,就可以实现企业数据治理的目标,还能提升数据治理的效率。 
    
    其次,针对核心数据标准主题选择要多维度考虑。
    
    数据标准只会关注跟业务关联度高的,能够促进业务的规范管理的数据。因此,数据标准制定,选择标准主题很重要。
    
    在这里,我们通过业务影响度、系统关联度和可实施性等三个方面对各主题做分析,获取各数据主题建设的重要、紧迫程度。
    
    其中,
    
    1、针对业务影响度,可以通过组织集中讲解、面谈解答以及调查问卷等多种调研活动;获得主题涉及的问题数量、问题影响业务数量、问题影响业务的重要性;
    
    2、应用系统关联度,可以通过分析各部门关注次数、各系统和系统模块使用次数;并通过对应用系统功能梳理,提炼相关实体;以及对相关实体,进行数据主题归结,形成主题在系统中的分布情况;
    
    3、可实施分析,可以通过产品手册、各业务部门体系文件,获得主题定义和分类,以及信息项情况;分析获得数据差异性;获得数据定义不一致程度、业务规则整合难度。
    

    通过分析,每个主题关系的业务系统数量不同,业务关注程度也不同,可实施程度不同(差异量,技术等),最终形成主题选择分析图表。在这里每一个度量维度都有加权,通过评分确定实施优先级,例如其中评分在满分的50%以上的,作为本期实施的依据,最终选定实施范围。例如上面的产品、财务、机构、客户四个主题。

    图片描述

    第二条关键点:数据标准要包括技术与业务两种属性

    1、数据标准主要是针对业务,企业很多业务的语义十分依赖业务人员的人工梳理,难度大效率低,很可能出现因为梳理人员没有及时梳理,而造成业务语义难以被及时发现和管理的问题。

    未来企业将会面临数字化转型,从非结构化的文档中,将大部分业务语义抽取出来,并统一管理,成为未来的发展趋势,这种能力可以通过自然语言分析技术来实现,企业可以通过综合多个材料中对同一业务的描述,分析出最新与最广泛认可的业务定义,由业务人员确认之后,识别出业务语义,这样大大减少了业务人员的工作量,提升了业务人员梳理业务语义的积极性。

    2、在企业数据治理中,任何一个数据标准,如果没有对应的技术手段,都将难以落地,所以企业建立数据标准时,需要加入信息项的英文名称,来和实际数据库表中的字段相对应。

    在数据标准中加入信息项的英文名称能给企业数据治理带来两方面的好处:

    在做模型设计的时候,标准可以直接与模型设计工具集成,设计模型时就可以直接引用标准。
    
    对已有系统,标准能够通过英文名称直接和应用系统的相关字段对应,自动发现与不符合标准的字段,并通过元数据直接通知给相应的系统。
    

    3、标准中有了技术和业务信息,还需要有效的关联才能发挥效用。对于企业数据管理来说,技术能弄懂业务的前提是技术与业务之间要有对应,这种对应不能靠大量的人工梳理完成,否则业务部门负担很重,积极性不高。需要能够通过技术手段,利用数据治理工具提供商的行业实践积累,形成业务与技术的自动关联库,自动完成业务与技术对应,将能大大减少业务人员的工作量,同时提升技术与业务关联的准确度,消除业务与技术之间的鸿沟。

    图片描述

    第三条关键点:数据标准要持续更新

    对于企业数据治理来说,有很多数据标准建立以后,往往只是一套书,没有根据企业业务发展及时做出更新,时间长了就成为了摆设,实际上,数据标准是需要随着企业的业务变化而不断进行修订的,比如在企业拓展新业务的时候,需要增加相应的标准进去,对于没有价值的标准,也要及时废弃。只有这样,才能保证数据标准一直能适应业务发展需要,促进标准落地。

    三、数据标准实施案例

    图片描述

    一般企业数据标准建设完,只停留在册子和书本上,缺乏落地手段,不能有效执行;另外,针对数据标准本身缺乏管理,不能有效适应新业务发展。

    某银行数据管理建设思路侧重于事前预防,将各领域数据管理的要求融入到系统研发当中,从需求编写和需求分析等数据产生源头进行管理。严格按照数据标准进行需求编写,结合数据质量管理、元数据管理串联整个软件生命周期。同时在这个过程中,不断的验证和修订数据标准,使得数据标准一直能够适应新业务的发展需要。

    通过项目实施:

    借助技术手段实现了数据标准的实施落地。在需求、开发、上线等各阶段都会有数标检查,实现全生命周期数据管控;
    
    通过系统管理,推进了数标的持续更新,保持了数据标准生命力。
    

    普元云计算专区:http://primeton.csdn.net/m/zone/primeton/index#

    普元公众号:

    图片描述

    展开全文
  • 企业级JavaEE开发框架bbossgroups作者尹平专访

    万次阅读 多人点赞 2012-10-16 13:53:08
    bbossgroups是国内首款集AOP、MVC、持久化、JSP标签库、分布式RPC服务、分布式事件框架于一身的企业级JavaEE开发框架,在Apache License Version 2.0 许可协议下开源。 官网地址:http://www.bbossgroups.com/ ...
    bbossgroups是国内首款集AOP、MVC、持久化、JSP标签库、分布式RPC服务、分布式事件框架于一身的企业级JavaEE开发框架,在Apache License Version 2.0 许可协议下开源。

    官网地址:http://www.bbossgroups.com/
    官方博客:http://yin-bp.iteye.com/

    为了使大家进一步了解这个框架,我们专访了bbossgroups的作者尹标平(ID:yin-bp)。

    欢迎大家推荐更多开源项目给我们,支持中国的开源项目发展,如果您和您的团队希望展示创业理念和有趣之处,或者有朋友正在创造这样的价值,请联系我们,发信到blog@csdn.com即可。


    先来个自我介绍吧! 


    尹标平,2001年大学毕业,一直从事JavaEE企业应用开发和架构设计工作,做过开发员、架构师、项目经理之类的,喜欢搞点开源方面的东东,比较拿得出手的开源项目只有bbossgroups。


    b


    bossgroups是什么?该项目的由来和发展历程? 


    bbossgroups是一个企业级开源JavaEE开发框架,简称为bboss,可以在官方博客中找到bboss的几乎所有资料。


    bboss的发展历史略显平淡,大致在2005年初开始bboss的开发工作。那时我所在的公司刚刚经历从CS向BS(也就是C++向Java)的技术转型,JavaEE的技术基础比较薄弱,老板决定要搞一套JavaEE的基础开发平台用于公司未来所有业务系统开发,这个平台早期的技术体系采用了Struts1和Hibernate(当时还没怎么接触过Spring),我作为骨干开发人员参与了这个平台的开发,我们发现Struts1和Hibernate的配置文件相当多而且繁琐,开发效率低下,HQL不能满足各种复杂业务查询需求,作为一个平台来说要能够满足在可以预见的未来的各行业各领域业务系统开发的需要,同时对技术体系能够进行高度的可定制化和扩展,而且当时有个客户明确要求我们提供的平台不能使用Hibernate(原因我们没有太多去追究)。正是由于这些因素,促成了我自发编写bboss框架的决定,也得到了当时公司老板的大力支持。

    bboss框架和平台基本上是同步进行开发,采用bboss逐步替换掉平台中早期引入的Struts 1和Hibernate。随着基础平台的顺利完成并在所在公司大范围应用,bboss也得到广泛的应用和推广,并帮助所在公司迅速完成了JavaEE技术的原始积累,使其拥有了自主开发的技术体系和基础开发平台,使得该公司处于当时同行业领域的领先地位。后需还基于bboss和基础平台开发出了内容管理系统、数据交换平台、开放服务平台以及监控系统等一系列广受欢迎的产品。

    bboss早期只提供了用于前端开发的标签库(bboss-taglib)、持久层框架(bboss-persistent)以及一个IOC容器(bboss-ioc)的雏形,三者可以独立使用,又可以很好地融合在一起使用。到2008年,这三个开发套件已经非常成熟,而且衍生出来一个解决集群节点之间缓存同步刷新的分布式事件框架(bboss-event),很好地解决了基础平台权限缓存和其他基础数据缓存部署在大量集群节点之间的数据实时同步问题。2008年年底,我将bboss开源了(基于Apache开源协议),bboss有了一个新的开始。

    2009年是bboss发展举步维艰的一年,也是bboss发展的重大转折点。当时很多公司都在搞基于BS可视化表单的快速开发平台。我所处的公司业务处于突飞猛进的时期,为了追求快速开发的目标,公司老板顺应潮流并着手构建类似的快速开发平台,并设想逐步原有基础开发平台。此时,我仍然继续坚持Bboss开发和维护工作。还好当时我带领一个小型的团队正在开发一套数据交换产品,该产品同样基于bboss进行开发,虽然没有外部需求,但是我们项目团队内部对bboss的需求非常旺盛,不断提出新的需求。通过不断地改进,bboss反而得到了长足的发展,在bboss-ioc的基础上开发了bboss的rpc开发套件(可以使用http/netty/mina/jms/webservice/jgroups等协议);基于bboss ioc提供了自己的序列化机制;基于bboss ioc集成了Apache CXF Webservice引擎等等。

    2010年bboss体系中增加了bboss-mvc这个新的成员,bboss-mvc基于bboss-ioc开发,完全实现了mvc2模型;同时进一步封装和简化持久层API,采用bboss ioc xml文件来配置和管理SQL语句。由于当时公司的快速开发平台应用情况不尽人意,bboss重新成为很多部门业务系统开发的首选开发框架。

    bboss的官网在2011年开通了,这里要特别感谢欧怀海和熊超两位高手的无私帮助,先后为bboss官网提供了非常棒的部署服务器。

    2011-2012年是新的bboss被广泛推广和快速成长的两年,先后增加了国际化机制、防止表单重复提交和跨站攻击机制;bboss 标签库提供更加丰富的数据展示标签和逻辑标签,与流行的jQuery框架进行很好的结合,增加了一系列安全标签;bboss持久层事务管理框架可以方便地托管并整合bboss/hibernate/mybatis等持久层框架的事务,很好地解决了:
    • bboss持久层和开源工作流activiti(基于mybatis)的事务一致性问题
    • Hibernate和和开源工作流activiti(基于mybatis)的事务一致性问题

    总体来说bboss从2005年诞生至今,已经走过7年的发展历程,在这7年里,个人觉得做的比较成功的一点就是在bboss和开发者之间营造了一种亲和关系,想开发人员之所需,帮助他们成功,同时也促成bboss的成功。

    感谢广大支持和使用bboss的朋友,他们的大力支持和鼓励才是bboss可持续发展的力量源泉,期望大家继续关注和支持bboss。


    bbossgroups包含哪些组件?主要功能?


    bbossgroups包含bboss mvc、bboss ioc、bboss持久层、bboss标签库、bboss rpc、bboss 工具包、bboss event七大部分,主要功能和特色如下:

    • aop/ioc 是整个bboss的基石,提供多种组件管理ioc容器类型,提供依赖注入(支持循环依赖注入、构造函数注入、属性注入)、组件生命周期管理、工厂模式、声明式事务配置等等。
    • rpc 丰富的通讯协议栈(http/netty/mina/jms/webservice/rmi/jgroups/restful),通过restful可以轻松实现服务路由功能,服务调用安全高效,提供可插拔的安全认证和rpc方法权限检测机制,可以通过rpc框架方便地获取bboss ioc中配置的组件的远程调用代理从而实现rpc调用。
    • distribute event framework (基于bboss rpc框架,分布式事件框架,可靠的分布式事件管理机制)。
    • jsp taglib 分页、树、列表、抽屉式、逻辑标签、map/list/arrary数据结构展示标签等等。
    • mvc(基于bboss ioc,灵活简单的参数绑定机制(基础参数绑定、list、map、数组),很好地支持json/jsonp,传统/html5文件上传下载,支持restful,word/pdf生成和自动转换插件,强大的安全认证过滤器,请求参数编码过滤器,灵活的请求跳转路径映射机制)。
    •  国际化组件(属性文件热加载、缓冲、高性能、支持从classpath和web应用目录中加载资源文件)。
    •  persistent,简洁而功能齐全的o/r mapping api,高效的查询行处理器,内置分页查询API(针对不同数据库进行优化),支持多数据源的API,全局事务管理(可整合托管bboss,ibatis,Hibernate的事务管理),很好地和业界主流数据源结合(dbcp,c3p0,proxool,weblogic,druid等),可采用bboss ioc来管理sql语句 (支持热加载,支持动态sql语句)。
    • xml-bean serializable(高效,很好地支持各种java数据类型和复杂对象结果,支持引用关系的序列化和反序列化,基于bboss ioc)
    • jms 开发套件,主要针对activimq。
    • 集成apache cxf webservice 简单方便地实现webservice服务发布和客户端代理调用
    • cluster with jgroups 可以轻松的集群节点的远程组件(bboss ioc管理的组件)的单播和组播调用。
    • quartz任务引擎管理组件 ,基于该组件可以非常方便地配置和管理quartz任务
    • 完备的框架监控机制,内置apache dbcp数据源监控,bboss mvc配置监控,bboss ioc组件配置监控,webservice服务配置监控等。 


    相比其他JavaEE框架,bbossgroups有哪些特色? 


    相比业界主流JavaEE框架(Spring、Struts、Hibernate、iBATIS/MyBatis),bboss到底有哪些特色,这个是很多朋友多次问起的问题。


    bboss基本上涵盖了Spring ioc、Struts、iBATIS/MyBatis三大框架的主要功能,可以这么说,采用一个bboss您就可以同时得到这三大框架的好处,而且为您免除了整合这些框架的烦恼。另外,在上面已经对bboss的功能和特色做了具体而详细的介绍,大家也可以访问bboss博客了解更加详细的内容。同时bboss每次新的版本发布时也会对新版本中增加功能特性和主要功能改进进行详细的介绍。可能很多内容介绍得比较粗糙,不能面面俱到,欢迎大家批评指正。


    有没有统计过bbossgroups目前的应用情况? 


    bboss是从项目里面提炼出来的,使用涉及的项目非常广泛,在此不一一罗列,主要应用的领域有:电子政务、企业/政府门户网站、基础产品(内容管理、开发平台、数据交换平台、开放服务平台)、教育、税务、运营商、公安、企业财务、工程机械制造、银行等等。



    可以这么说,bboss不仅为采用它的项目团队和公司带来直接的经济收益,而且为他们带来事业和工作上的成就感,为企业培养一批批优秀的开发人员;基于bboss开发的系统无时无刻都在为用户创造着价值。


    如何基于bbossgroups开发项目? 


    我们为bboss的初学者提供了一个入门级教程,可以帮助大家快速上手bboss——《搭建自己的bbossmvc eclipse开发工程,编写第一个实例


    在bboss每个发布的版本中提供了一些bestpractice,涉及bboss的主要功能demo。

    你可以随时在github上获取bboss的最新源代码,最新的版本为bboss3.6.0分支(以实际情况为准):https://github.com/bbossgroups/bbossgroups-3.5

    源码的构建方法,可以参考:bboss 版本ant构建方法

    如果你在实际开发过程中碰到问题或者需要获取bboss功能的具体使用介绍时,一种途径是通过bboss的官方博客查找相关资料,另外一个途径就是加入bboss的QQ交流群,在群中发帖留言,群号:21220580、166471282、166471103、154752521、3625720。

    最后可以随时通过bboss官网跟踪bboss的最新发展动态。


    bbossgroups采用哪种开源协议?


    bbossgroups采用的开源协议是Apache License Version 2.0 ,完全免费开放,文档完全免费,而且为使用者提供免费的开发培训。


    使用bbossgroups开发项目需要注意事项?


    Bbossgroups最新版本所需的JDK版本最好是JDK 1.6或以上版本。


    bbossgroups开发团队现状?其他开发者如何参与贡献?


    Bbossgroups开发团队成员目前只有我一个人,希望有更多的有志之士加入进来,为bboss注入新的思想和特色。bboss的源代码托管在github上,可以通过以下地址获取:

    代码:
        
    git clone git://github.com/bbossgroups/bbossgroups-3.5.git  

    后续新的开发人员可以通过github来贡献和提交代码。


    bbossgroups未来的发展计划? 


    Bbossgroups未来的发展计划为:
    •  完善bboss各模块现有功能
    •  完善bboss开发文档
    •  推广bboss
    •  根据实际项目需要随时引入新的功能 




    展开全文
  • RFC6020 - YANG语言标准中文

    万次阅读 多人点赞 2016-08-05 14:49:04
    该集合可能在定义处的module被使用,也可能在包含它的modules使用,还可能在导入它的modules被使用。grouping声明不是一种数据定义声明,它不会在schema node定义任何节点。 identifier —— 通过名字,...

    YANG - A Data Modeling Language for the Network Configuration Protocol (NETCONF)

    该标准脱胎于草案draft-ietf-netmod-yang,该草案从2008年5月开始,先后经历了13个草案版本,最终于2010年8月成为建议标准(Proposed Standard)。本文档的翻译时间开始于2016年5月12日。

    本文档有勘误表存在。

    摘要

    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的子节点。

    4. YANG总览

    4.1 功能总览

    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,RFC2578RFC2579)保持了兼容。基于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 示例:

       <host-name>my.example.com</host-name>
    

    “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 示例:

     <domain-search>high.example.com</domain-search>
     <domain-search>low.example.com</domain-search>
     <domain-search>everywhere.example.com</domain-search>
    

    “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";
             }
         }
     }
    

    NETCONF XML 示例:

     <system>
       <login>
         <message>Good morning</message>
       </login>
     </system>
    

    “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;
         }
     }
    

    NETCONF XML 示例:

     <user>
       <name>glocks</name>
       <full-name>Goldie Locks</full-name>
       <class>intruder</class>
     </user>
     <user>
       <name>snowey</name>
       <full-name>Snow White</full-name>
       <class>free-loader</class>
     </user>
     <user>
       <name>rzell</name>
       <full-name>Rapun Zell</full-name>
       <class>tower</class>
     </user>
    

    “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 "joe@acme.example.com";
         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;
                     }
                 }
             }
         }
     }
    

    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;
         }
     }
    

    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              |
       +---------------------+-------------------------------------+
    

    “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;
     }
    

    NETCONF XML 示例:

     <completed>20</completed>
    

    “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;
         }
     }
    

    NETCONF XML 示例:

     <peer>
       <destination>
         <address>192.0.2.1</address>
         <port>830</port>
       </destination>
     </peer>
    

    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";
                 }
             }
         }
     }
    

    “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;
                   }
               }
           }
       }
    }
    

    NETCONF XML 示例:

     <food>
       <pretzel/>
       <beer/>
     </food>
    

    “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";
             }
         }
     }
    

    这个例子定义了一个“uid”的leaf node,该node仅在user的class不等于wheel的时候才有效。

    如果一个module增强了另一个module,则数据的XML表示将会影响增强它的module的前缀。比如,如果上一个例子的augment是放在一个“other”前缀的module中,则其XML看起来应该是这样的:

    NETCONF XML 示例:

     <user>
       <name>alicew</name>
       <full-name>Alice N. Wonderland</full-name>
       <class>drop-out</class>
       <other:uid>1024</other:uid>
     </user>
    

    “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;
             }
         }
     }
    

    NETCONF 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”的声明可以在Section 7.13中找到。

    4.2.10 Notification定义。

    YANG的notification定义和NETCONF适配。YANG的数据定义声明被用来为notification的内容建模。

    YANG Example:

     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;
         }
     }
    

    NETCONF XML Example:

     <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和rpc都是NETCONF中的定义,虽然大概明白什么意思,但是具体就不清楚了,需要去NETCONF的标准中去查看定义。

    “notification”的声明可以在Section 7.14中找到。

    5. 语言概念

    5.1 modules和submodules

    在YANG语言中,module是基本单位。每个module都定义一个数据模型。一个module能够定义一个完整的模型,或者对当前数据模型做额外扩展。

    submodules是module的一部分,能够为一个module提供相关定义。一个module能包含任意数量的submodules,但是每个submodule只能属于一个module。

    所有标准的modules和submodules的名字都 MUST 是唯一的。我们 RECOMMEND 企业级modules的开发者选择和标准模型以及其他企业modules不冲突的名字,比如说,使用企业或组织名字作为module名字的前缀。

    一个module使用“include”声明包含它的submodules,使用“import”声明引入外部的modules。相似的,一个submodule会使用“include”声明引用同一个module中的其他submodules,使用“import”声明引用其他modules。一个module或submodule MUST NOT 包含其他modules中的submodules,一个submodule MUST NOT 导入它自己所在的module。

    导入(import)和包含(include)声明使用如下:

    • 如果一个module或submodule需要引用来自外部的module,外部的module MUST 被imported。
    • 如果一个module需要引用其内部的某个submodule,这个module MUST include这个submodule。
    • 如果一个submodule需要引用同一个module内部的其他submodule,则这个submodule MUST include另一个submodule。

    在modules/submodules的imports和includes中,MUST NOT 形成环形调用链。比如,如果submodule “a”包含了submodule “b”,则“b”就不能包含submodule “a”了。

    当在一个外部module的定义被引用时, MUST 使用局部定义的前缀,后面跟着冒号“:”,然后是具体使用的外部module的id。对本地module定义的引用可以使用前缀,也可以不使用。由于built-in类型不属于任何module,所以对built-in类型的引用不能使用任何前缀。

    5.1.1 Import and Include by Revision

    随着时间的推移,已经发布的modules会慢慢演进出新的版本。为了支持这样的正常演进过程,modules在被其他module import时需要使用其revisions。当一个module完成时,它会基于当前时间使用可用的带有特定revisions的其他modules。如果后来,被imported的modules更新了,该module不会受到影响。当这个module的作者准备将“import”的module更新到最新版本,只需要修改“revision”字段就可以了。

    对于submodule来说,方案相似不过更加简单。一个module或者submodule,在包含其他的submodule的时候都要指定被包含submodules的revision。如果一个submodule改变了,任何包含它的其他module或者submodules都需要被更新。

    比如,module “b” 导入了module “a”:

     module a {
         revision 2008-01-01 { ... }
         grouping a {
             leaf eh { .... }
         }
     }
    
     module b {
         import a {
             prefix p;
             revision-date 2008-01-01;
         }
    
         container bee {
             uses p:a;
         }
     }
    

    当module “a” 的作者发布了一个新的revision,新版本的更改可能不为“b”所接受。如果“b”接受,则需要更新其导入“a”的import语句中的revision版本。

    5.1.2 Module分层

    YANG能支持数据模型的多层次划分,在该划分中,数据可能有不止一个top-level(顶级)的节点。拥有多个top-level节点的数据模型有时候是更加方便的。

    NETCONF协议能够在<config><data>元素中包含任何XML内容作为载荷。YANG模型中的顶级结点在上述两种元素中以任意顺序,作为子节点存在。在这些子节点中,要保证NETCONF消息已经封装成正确的XML格式了。

    比如:

     module my-config {
         namespace "http://example.com/schema/config";
         prefix "co";
    
         container system { ... }
         container routing { ... }
     }
    

    在NETCONF中被封装为:

     <rpc message-id="101"
          xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
       <edit-config>
         <target>
           <running/>
         </target>
         <config>
           <system xmlns="http://example.com/schema/config">
             <!-- system data here -->
           </system>
           <routing xmlns="http://example.com/schema/config">
             <!-- routing data here -->
           </routing>
         </config>
       </edit-config>
     </rpc>
    

    除了YANG定义之外的rpc,message-id什么的都搞不懂。还需要看一下NETCONF啊。

    5.2 文件格式

    YANG modules和submodules通常都会以文件的形式存储,每个module或者submodule一个文件。文件的命名格式 SHOULD 是这种格式:

    module-or-submodule-name ['@' revision-date] ( '.yang' / '.yin' )
    

    YANG编译器能够通过文件名找到导入的modules和包含的submodules。当使用YANG语言定义modules的时候,出于性能和manageability的考虑,编译器可能会分别编译每一个submodules。在submodules的编译期间,errors和warnings不能被检测到。直到将submodules并入module的时候,才会发现错误和警告。

    5.3 XML Namespace

    所有的YANG定义都包含在YANG module中,每个YANG module都会和特定的XML namespace XML NAMES绑定,该命名空间是全局唯一的URI RFC3986。NETCONF的客户端和服务端在封装数据的时候,使用这个命名空间。

    modules的Namespace发布在rfc4844中, MUST 由IANA分配,可见Section 14。

    私有module的namespace分配由拥有该module的组织分配。Namespace URIs的分配必须保证不能与标准的modules冲突,不能与其他私有的modules冲突,可以在namespace中使用组织/公司名字以避免明明冲突。

    “namespace”声明可以在Section 7.1.3见到。

    5.3.1 YANG XML Namespace

    YANG 为NETCONF的 <edit-config><error-info>内容定义了XML namespace。这个namespace的名字是“urn:ietf:params:xml:ns:yang:1”。

    5.4 解析Grouping,Type,和Identify名

    Gouping,Type,和Identify的名字是在它们被定义的地方被解析的,而不是在它们被使用的地方被解析的。groupings, typedefs,identifies的使用者并不被强制要求导入modules或者包含submodules,以满足原始定义的引用要求。这种特性类似于传统编程语言中的静态变量作用域。

    比如,如果一个module定义了一个grouping,在其中引用了一个type。当这个grouping在另一个module中被引用的时候,该type在原来的module的上下文中被解析,而不是在第二个module中被解析。如此一来就不用担心多个module共同定义同一个type时候引起的冲突问题了。

    5.5. Nested Typedefs和Groupings

    在很多YANG statements中,typedefs和groupings都可能出现嵌套的情况。在层级结构中,它们在语义上局限于被定义的层级(也就是说解析的时候不会波及到其他层级)。这使得types和groupings可以定义在和被使用的地方接近的地方,而不是放到层级结构的顶级。这种使用处定义的特性增强了可读性。(Typedefs and groupings may appear nested under many YANG statements, allowing these to be lexically scoped by the hierarchy under which they appear. This allows types and groupings to be defined near where they are used, rather than placing them at the top level of the hierarchy. The close proximity increases readability.

    作用域(scoping)的作用使得在不同submodules定义的types可以出现命名冲突,因为它们的作用域没有交集。

    最后,作用域使得module的作者能够使得他们定义的types和groupings能够只对他们的module或submodule有效,防止了其他人的重用。由于只有顶级的types和groupings能够在module/submodule外部被使用,开发者能够有更多的控制能力,控制module的哪些部分要对外开放,哪些部分要在内部保持私有。

    作用域的定义 MUST NOT 覆盖更高级别的作用域的定义。当在schema层级结构中,当更高级别中已经定义了,则更低级别中不能再定义相同的“types”和“groupings”了。

    对于没有前缀的type或grouping的引用,或者使用当前module名作为前缀的引用,会被解析为和type或grouping声明最匹配的结构。(A reference to an unprefixed type or grouping, or one which uses the prefix of the current module, is resolved by locating the closest matching “typedef” or “grouping” statement among the immediate substatements of each ancestor statement.

    5.6 一致性

    一致性(conformance)是衡量一个设备实际上与model契合的程度。通常来说,设备需要如实完全实现model的定义,这样一来上层应用才能按照model的定义来看待下面的设备。设备与model的差异会降低model的可用性,同时使得使用该model的application更加脆弱。

    YANG针对一致性有三种检查机制:

    • model的基础行为检查
    • model可选特性的检查
    • 和model之间的偏差

    接下来我们会挨个讨论每一种机制。

    5.6.1 基础行为

    model定义了NETCONF的client和server之间的constract(协议),这使得通信双方能够互相理解对方发送的模型化数据背后蕴含的语法和语义。YANG的优点就是constract的优点。

    5.6.2 可选特性

    在很多models中,作者会允许models中的某些部分在有一定先决条件的情况下才会出现/禁止出现。设备可以决定,是否支持model中定义的可选功能。

    比如,一个syslog data model可能会选择支持本地存储日志的能力,但是model作者知道,在实际设备中,只有当这个设备有本地存储器的时候才有可能支持该功能。如果设备上没有本地存储器,则application就不能通知设备去存储日志。

    YANG通过名为“feature”的结构支持这种可选特性的机制。features使得模型作者能够让设备根据实际情况有选择实现一些可选的特性。这样一来,在model中就能表现一些只有部分设备支持的特性。这些特性被包含在model的定义中,能够使得不同设备的模型尽可能保持一致性,让application能够获知哪些特性被支持,并在此基础上对设备进行操作。

    一个module可以声明任意数量的features,这些特性用字符串id做识别。如果一个设备支持某个feature,则module中对应的部分对该设备来说就是可用的;反之亦然。

    features是用“feature”声明定义的。如果该feature是有条件的(conditional),则需要使用“if-feature”声明。

    更多细节可见Section 7.18.1

    还是不太明白feature的应用实例。

    5.6.3 偏差(deviations)

    在理想情况下,所有的设备都应该完全实现model的定义,不会和model出现任何偏差。但是实际情况下,设备总会和model有各种各样的差异存在。为了让YANG能够支持针对实际存在的偏差的自动处理,设备上必须有一种机制能够通知applications它和model之间的偏差。

    比如,一个BGP module能支持任意多的BGP peers,但是一个特定的设备可能最多只能支持16个peers。任何application发送的第17个peer的连接请求都会失败。相比较于设备用错误消息通知application,更好的解决方法是application从一开始就知道16个peers的限制,并且能够避免用户申请注定失败的第17个peer连接。

    设备的deviations使用“deviation”声明,它使用在schema tree中表示一个节点的字符串作为参数。The contents of the statement details the manner in which the device implementation deviates from the contract as defined in the module.

    更多细节可见Section 7.18.3

    5.6.4 在消息中宣告一致性(Conformance)信息

    命名空间URI MUST 作为一种能力(capability),在NETCONF的消息中向外通告,表示NETCONF服务器支持YANG module。该URI的格式 MUST 如下:

     capability-string   = namespace-uri [ parameter-list ]
     parameter-list      = "?" parameter *( "&" parameter )
     parameter           = revision-parameter /
                           module-parameter /
                           feature-parameter /
                           deviation-parameter
     revision-parameter  = "revision=" revision-date
     module-parameter    = "module=" module-name
     feature-parameter   = "features=" feature *( "," feature )
     deviation-parameter = "deviations=" deviation *( "," deviation )
    
    • “revision-date”表示NETCONF服务器实现的module的revision
    • “module-name”表示module的名字,如同“module”声明一样
    • “namespace-uri”表示这个module的namespace URI,如同在“namespace”声明中出现的一样
    • “feature”表示设备实现的可选的feature
    • “eviation”表示定义了设备的偏差的module的名字

    在以上的参数列表中,每个参数 MUST 出现一次。

    5.6.4.1 Modules

    服务器通过消息通告它所支持的modules的名字。Module的namespaces是在capability字符串中作为基础URI编码的,mdule的名字被编码为“module”参数放到基础URI中。

    一个服务器 MUST 声明它所实现的所有modules的所有revisions。

    比如,下面的消息声明了一个module “syslog”。

        <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
          <capability>
            http://example.com/syslog?module=syslog&amp;revision=2008-04-01
          </capability>
        </hello>
    5.6.4.2 Features

    服务器通过消息通告它所支持的features的名字。在消息中,features作为包含在URI中的“features”参数编码的。这个参数的值是以逗号为分隔符的feature名的列表。

    比如,下面的消息声明了一个module,“syslog”,并告诉客户端它所支持的名为“local-storage”的feature。

    <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
      <capability>
        http://example.com/syslog?module=syslog&amp;features=local-storage
      </capability>
    </hello>
    5.6.4.3 偏差(Deviations)

    设备的偏差是通过“deviations”参数声明的。“deviations”参数的值是以逗号为分隔符的包含deviations的modules的列表。

    比如,下面的消息通告了两个modules,告诉客户端它偏离module “syslog”的程度,这个程度具体是通过module “my-devs”声明出来的。

       <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
           <capability>
             http://example.com/syslog?module=syslog&amp;deviations=my-devs
           </capability>
           <capability>
             http://example.com/my-deviations?module=my-devs
           </capability>
         </hello>

    但是这个偏差具体怎么描述也没有个说明,它的内容和“syslog”有怎样的关系?

    5.7 Data Store Modification

    Data models可能允许服务器选择不同的configuration data store的实现,而不仅仅是直接明确地通过NETCONF协议消息完成。比如,一个data model可能定义了一些系统生成的分配的值作为leafs,但是客户端可能并不支持。一种指定环境变量的通用机制(前提是这些环境变量允许修改)超出了本文档的讨论范围。

    6 YANG Syntax

    YANG语法类似于【RFC3780】定义的SMIng,以及编程语言C和C++。这种语法之所以和C相似,主要是为了可读性。since YANG values the time and effort of the readers of models above those of modules writers and YANG tool-chain developers. This section introduces the YANG syntax.

    YANG modules使用【RFC3629】定义的UTF-8作为字符编码格式。

    6.1 词汇的令牌化(Lexical Tokenization)

    YANG modules在解析时会被分为多个tokens。本小节详细解释解析这些tokens的规则。YANG的令牌化规则是简单而强大的。简单之处在于其力图保持解析器的实现简单,强大之处在于模型设计者能够以一种易读的格式表现他们设计的models。

    6.1.1 注释(Comments)

    Comments是C++风格的。单行注释开始于“//”,结束于本行。块注释开始于“/*”,结束于“*/”。

    6.1.2 Tokens

    YANG中的一个token是一个keyword,string,semicolon(“;”),或者braces( “{” 或 “}” )。一个string可以是quoted或unquoted的。一个keyword可以是本文档中定义的YANG的关键词,或者是后面跟着冒号“:”,冒号后面跟着语言扩展关键词的前缀id。keywords是大小写敏感的。id的正式定义可见section 6.2。

    什么是quoted和unquoted?意思是引号包括的和不用引号包括的。

    6.1.3 引号包裹(Quoting)

    如果一个string包含任何空格,制表符,分号(“;”),大括号( “{” 或 “}”),注释符号(“//”,“/*”,或“*/”),则它 MUST 用双引号或者单引号包括。

    如果一个用双引号包括的string中包含一个换行符,换行符后面跟着的是空格或者制表符,该空格或制表符通常用来控制YANG文件中的文本布局。这些用于增强文本显示效果的留白在解析时会被从string中删掉,一直到第一个非空白字符为止。在该处理流程中,一个制表符被认为是8个空格符。

    如果这个用双引号包括的string中在换行符前包含了空格或者制表符,这种行尾空格也会被从string中删掉。

    一个单括号包裹的string(“””)则会保留单括号内的每一个字符。单括号字符不能出现在单括号包括的string中,即便使用反斜杠(“\”)做了转义也不可以。

    在一个双括号包括的string理,使用转义字符(也就是反斜杠)会引入一个特殊字符,这取决于该转义字符后面跟着的是哪个字符:

    \n      new line
    \t      a tab character
    \"      a double quote
    \\      a single backslash
    

    如果一个括号包裹的string后面跟着一个加号(“+”),然后跟着另一个括号包裹的string,则这两个strings会被首尾衔接在一起,合并为一个string。在双括号包括的strings进行合并之前,该string要先完成空白字符的删除,以及转义字符的替换。

    6.1.3.1 Quoting例子

    下面的strings是等价的:

         hello
         "hello"
         'hello'
         "hel" + "lo"
         'hel' + "lo"

    下面的例子展示了一些特殊字符:

     "\""  - string containing a double quote
     '"'   - string containing a double quote
     "\n"  - string containing a new line character
     '\n'  - string containing a backslash followed
             by the character n
    

    下面的例子展示了一些非法的字符串:

     ''''  - a single-quoted string cannot contain single quotes
     """   - a double quote must be escaped in a double-quoted string
    

    下面的字符串是等价的:

         "first line
            second line"
    
     "first line\n" + "  second line"          
    

    6.2 Identifiers

    6.1.2中提到的id。

    Identifiers被用来标识不同类型的YANG items。每个identifier都开始于一个大写,小写的ASCII字幕,或者是一个下划线,后面跟着0个或多个ASCII字幕,数字,下划线,连字符以及点。具体的实现 MUST 支持64个字符的长度。Identifiers是大小写敏感的。其语法规则的正式定义可见Section 12。Identifiers能被指定为quoted或unquoted strings。

    其实看了也不明白这个identifier的具体用途在哪里

    6.2.1 Identifiers和它们的Namespaces

    每个identifier在一个namespace中都是有效的,而namespace取决于YANG item被定义的类型。所有的定义在一个namespace中的identifiers都必须是唯一的。

    • 所有的module和submodule的名字都共享同一个全局的module identifier namespace。
    • 在module以及它的submodules中定义的所有扩展名都共享同一个extension identifier namespace。
    • 所有定义在module以及它的submodules的identity names都共享同一个identity identifier namespace。
    • 所有定义在module以及它的submodules的父节点或者顶级节点的派生类型的名字(derived type names)都共享同一个type identifier namespace。这个namespace对于该父节点或者module的所有下行节点都有效。这意味着任何下行节点都有可能使用typedef,并且 MUST NOT 定义和其它type名相同的名字。
    • 所有定义在module以及它的submodules的父节点或者顶级节点的grouping names都共享同一个grouping identifier namespace。这个namespace对于该父节点或者module的所有下行节点都有效。这意味着任何下行节点都有可能使用grouping,并且 MUST NOT 定义和其它grouping名相同的名字。
    • 所有定义在module以及它的submodules的父节点或者顶级节点的leafs,leaf-lists,lists,containers,choices,rpcs,notifications以及anyxmls(直接或者通过“use”声明定义的 )都共享同一个identifier namespace。这个namespace对于该父节点或者module都有效,除非父节点是一个case node。在那种情况下,这个namespace对于非case或choice节点的最近的祖先节点。
    • 所有在包含在“choice”中的“case”都共享同一个case identifier namespace。这个namespace在父choice node中有效。

    这里还是有问题啊,第六项中,这个namespace对于该父节点或者module有效,而不是对该父节点或者module的所有下行节点都有效。这里是不是有错误啊?
    另外,顶级节点的作用范围是不是就对应着整个module啊。

    YANG语言中允许前向引用(Forward references)。

    6.3 声明(Statements)

    一个YANG module包含了一系列的statements。每个statement开始于一个keyword,后面跟着0个或一个参数,然后或者跟着一个分号表示结束,或者跟着用大括号包裹的substatements块:

     statement = keyword [argument] (";" / "{" *statement "}")
    

    如果Section 6.1.2的定义,这个参数是一个string。

    6.3.1 语言扩展(Language Extensions)

    在一个module中,可以使用“extension”关键词(见Section 7.17)引入YANG extensions。扩展也可以被其它modules使用“import”声明导入(见Section 7.1.5)。当一个被导入的扩展被使用时,该扩展的关键词 MUST 使用该扩展被定义的module的名字作为前缀以示区别。如果扩展在它被定义的module中使用,则其关键词也 MUST 使用module的前缀。由于submodules不能包括其parent module,因此,所有需要在submodules中用到的扩展都 MUST 定义在submodule中。然后其它的submodules能够通过包含该submodule使用该扩展。

    复习一下,submodule叫include,module叫import。

    如果一个YANG编译器不支持特定的扩展,具体表现为在一个YANG module中出现未知的statement(见Section 12),则整个未知的statement包含的内容 MAY 被编译器忽略。

    6.4 XPath Evaluations

    XPath的简介可见http://www.w3school.com.cn/xpath/xpath_intro.asp

    XPath 是一门在 XML 文档中查找信息的语言。XPath 用于在 XML 文档中通过元素和属性进行导航。XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档节点(或称为根节点)。

    YANG依赖XML Path Language(XPath) 1.0,将其作为标记表达节点之间的引用和依赖关系。NETCONF的客户端和服务端并不强制要求实现XPath解释器,但是 MUST 确保data model中编码的requirements是强制执行的。执行的方式由实际实现决定。XPath表达式 MUST 在语法结构上保证正确无误,所有使用的前缀 MUST在当前的XPath context中是现成可用的(见Section 6.4.1)。有种实现会选择手动实现这些,而不是直接使用XPath表达式。

    什么叫确保data model中编码的requirements是强制的。原文是

    NETCONF clients and servers are not required to implement an XPath interpreter, but MUST ensure that the requirements encoded in the data model are enforced. The manner of enforcement is an implementation decision.

    The data model used in the XPath expressions is the same as that used
    in XPath 1.0 [XPATH], with the same extension for root node children
    as used by XSLT 1.0 [XSLT] (Section 3.1). Specifically, it means
    that the root node may have any number of element nodes as its
    children.

    6.4.1 XPath Context

    所有的YANG XPath表达式都共享下面的XPath context定义:

    • The set of namespace declarations is the set of all “import” statements’ prefix and namespace pairs in the module where the XPath expression is specified, and the “prefix” statement’s prefix for the “namespace” statement’s URI.
    • Names without a namespace prefix belong to the same namespace as the identifier of the current node. Inside a grouping, that namespace is affected by where the grouping is used (see Section 7.12).
    • The function library is the core function library defined in [XPATH], and a function “current()” that returns a node set with the initial context node.
    • The set of variable bindings is empty.

    The mechanism for handling unprefixed names is adopted from XPath 2.0 [XPATH2.0], and helps simplify XPath expressions in YANG. No ambiguity may ever arise because YANG node identifiers are always qualified names with a non-null namespace URI.

    The context node varies with the YANG XPath expression, and is specified where the YANG statement with the XPath expression is defined.

    6.5 Schema Node Identifier

    这一块可是重中之重啊,在ODL的YANGTools中,首先要做的就是解析参数为SchemaNodeIdentifier。

    一个schema node identifier是一个string,表明了schema tree中的一个节点。它有两种表达形式,“absolute”(绝对路径)和“descendant”(相对路径),其规则分别由Section 12中的“absolute-schema-nodeid”和“descendant-schema-nodeid”制定。一个shema node identifier是由用斜杠(“/”)分隔的不同id组合而成的path组成的。在一个absolute schema node identifier中,第一个斜杠后面的第一个identifier是本module或所有其它被导入的modules的顶级schema node。

    定义在外部modules的对identifiers的引用 MUST 使用合适的前缀描述,在当前module以及它的submodules中引用的identifiers MSY 使用前缀。

    比如,为了表示在顶级节点“a”下的子节点“b”,可以使用字符串“/a/b”。

    7 YANG Statements

    接下来的小节描述了所有的YANG statements。

    需要明确一点,即便是在YANG中没有定义任何substatements的statement也能有设备商制定的扩展作为substatements。比如,“description”声明在YANG定义中没有任何substatements,但是下面的写法是合法的:

     description "some text" {
         acme:documentation-flag 5;
     }
    

    7.1 Module Statement

    “module”声明定义了module的名字,将所有属于该module的声明都集中在一起。“module”声明的参数就是该module的名字,后面跟着一块substatements,其中包含了该module具体的信息。module的名字服从Section 6.2中针对identifiers的规则。

    在RFC streams 【RFC
    4844
    】中发布的modules的名字 MUST 由IANA分配,可见Section 14。

    私有的module的名字是由拥有该module的组织分配的。 RECOMMENDED 私有module的名字和标准中的modules以及其它组织的module没有命名冲突。

    一个module的典型布局如下:

     module <module-name> {
    
         // header information
         <yang-version statement>
         <namespace statement>
         <prefix statement>
    
         // linkage statements
         <import statements>
         <include statements>
    
         // meta information
         <organization statement>
         <contact statement>
         <description statement>
         <reference statement>
    
         // revision history
         <revision statements>
    
         // module definitions
         <other statements>
     }
    

    7.1.1 module的substatements

                 +--------------+---------+-------------+
                 | 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        |
                 +--------------+---------+-------------+
    

    上面的0..1,表示可以出现0次到1次,0..n表示可以出现任意次数,1表示能且仅能出现一次。

    7.1.2 yang-version声明

    “yang-version”是可选的,指定了本module使用的YANG语言的版本号。这个声明的参数是一个字符串。如果出现,它必须包含值“1”,这是YANG语言目前的版本号,也是默认的版本号。

    version 1.1已经有了。不过还不知道是哪个RFC。

    对于值非“1”的“yang-version”的处理超出了本文档的讨论范围。任何定义更高版本的文档都需要保持版本向前兼容。

    7.1.3 namespace声明

    “namespace”声明定义了module中所有的identifiers所属的XML namespace,除了定义在一个grouping中的data node identifiers以外(见Section 7.12)。它的参数是这个namespace的URI。

    详情可减Section 5.3。

    7.1.4 prefix声明

    “prefix”声明呗用来定义和module以及它的namespace相关联的前缀。“prefix”声明的参数是一个前缀字符串。这个字符串 MAY 指向包含在本module中的定义,比如“if:ifName”。prefix遵循和identifier相同的规则(见Section 6.2)。

    当在“module”声明中使用它时,“prefix”声明定义了当该module被其它module导入时需要使用的前缀。为了提高NETCONF XML的可读性,一个使用该前缀生成XML或者XPath的NETCONF的客户端或者服务端 SHOULD 使用这个前缀,除非出现了冲突。(To improve readability of the NETCONF XML, a NETCONF client or server that generates XML or XPath that use prefixes SHOULD use the prefix defined by the module, unless there is a conflict.

    当在“import”声明中使用它时,“prefix”声明定义了访问被导入module中的定义时需要使用的前缀。当需要引用一个被导入module的identifier时,被导入module的前缀字符串会被放在identifier前面,用冒号隔开,比如“if:ifIndex”。为了提高YANG modules的可读性,module中定义的prefix SHOULD 在该module被导入时使用,除非出现了prefix conflict。如果出现了冲突,比如两个拥有同样prefix名的不同的modules同时被导入,则至少有一个 MUST 改变其prefix。

    所有的prefixes,包括module自己本身的prefix,都 MUST 在该module或者submodule内部保持唯一。

    这里用了module或者submodule内部保持唯一。

    7.1.5 import声明

    “import”声明使得一个module的定义能够在另一个module或submodule内部被使用。它的参数是被导入的module的名字,其后跟着一块包含具体导入信息的substatements。当一个module被导入时,导入它的module可能:

    • 使用被导入module或者它的submodules中的任何grouping和typedef。
    • 使用被导入module或者它的submodules中的任何extension,feature,以及identity。
    • 使用被导入module的schema tree中的“must”,“path”,以及“when”声明中的任何node,或者作为“augment”和“deviation”声明的target node。

    The mandatory “prefix” substatement assigns a prefix for the imported module that is scoped to the importing module or submodule. Multiple “import” statements may be specified to import from different modules.

    当可选的“revision-date” substatement在“import”声明中出现时,任何本地module的定义中引用的typedef,grouping,extension,feature以及identity都是从指定revision的module中导入的。如果指定的revision不存在,则会出现错误。如果没有“revision-date”出现,则导入的module的revision不确定。

    对于同一个module的多个revisions的导入是 MUST NOT 的。

                        The import's Substatements
    
                 +---------------+---------+-------------+
                 | substatement  | section | cardinality |
                 +---------------+---------+-------------+
                 | prefix        | 7.1.4   | 1           |
                 | revision-date | 7.1.5.1 | 0..1        |
                 +---------------+---------+-------------+
    
    7.1.5.1 import的revision-date声明

    “revision-date”声明用来指定module的具体版本号。其值 MUST 和被导入module的“revision”声明的值匹配。

    7.1.6 include声明

    “include”声明被用来将某个submodule的内容对于其父module,或者父module之下的其他submodule可用。其参数是一个identifier,表示被包含的submodule的名字。modules只能包含属于它的用“belongs-to”声明定义的submodules,submodules只能包含和它属于同一个module的其他submodule。

    当一个module包含了一个submodule,它就会将这个submodule的内容组合进本module的node hierarchy中。当一个submodule包含了另一个submodule,则另一个submodule的定义对于当前的submodule就是可用的。

    当可选的“revision-date” substatement出现,指定revision的submodule会被包含到module中。如果指定revision的submodule不存在,则会出现错误。如果没有“revision-date” substatement出现,则没有定义哪个revision的submodule会被包含。

    对于同一个submodule的多个revisions的导入是 MUST NOT 的。

                       The includes's Substatements
    
                 +---------------+---------+-------------+
                 | substatement  | section | cardinality |
                 +---------------+---------+-------------+
                 | revision-date | 7.1.5.1 | 0..1        |
                 +---------------+---------+-------------+
    

    7.1.7 organization声明

    “organization”声明定义了对该module负责的团体名。其参数是特定组织的文本描述的字符串。

    7.1.8 contact声明

    “contact”声明提供了该module的相关联系信息。该参数是一个字符串,包含了指定联系人的名字,邮件地址,电话号码,电子邮箱等信息,技术相关的疑问都可以咨询他。

    7.1.9 revision声明

    “revision”声明指定了该module的编辑版本历史,包括最初的一版。一系列的revision声明能够详细描述该module定义上发生的改变细节。其参数是一个日期字符串,格式为“YYYY-MM-DD”,后面跟着一块包含详细revision信息的substatements。一个module SHOULD 至少有一个初始的“revision”声明。对于每次发布的修改,都 SHOULD 增加一个revision。

    7.1.9.1 revision的substatement
                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | description  | 7.19.3  | 0..1        |
                 | reference    | 7.19.4  | 0..1        |
                 +--------------+---------+-------------+
    

    7.1.10 使用用例

     module acme-system {
         namespace "http://acme.example.com/system";
         prefix "acme";
    
         import ietf-yang-types {
             prefix "yang";
         }
    
         include acme-types;
    
         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
             "The module for entities implementing the ACME protocol.";
    
         revision "2007-06-09" {
             description "Initial revision.";
         }
    
         // definitions follow...
     }
    

    7.2 submodule声明

    YANG中最基本的单位是module,一个YANG module本身能够由多个submodules构成。submodules的存在使得module设计者能够将一个复杂的model分割成多个共用同一个namespace的submodules,而namespace是由module定义的。

    “submodule”声明定义了submodule的名字,将属于该submodule的所有声明都整合到了一起。其参数是submodule的名字,后面跟着相关的详细substatements信息。submodule名字遵从identifiers的规则,可见Section 6.2。

    在RFC streams 【RFC4844】中发布的submodules的名字都 MUST 由IANA分配,可见Section 14。

    Private submodule names are assigned by the organization owning the
    submodule without a central registry. It is RECOMMENDED to choose
    submodule names that will have a low probability of colliding with
    standard or other enterprise modules and submodules, e.g., by using
    the enterprise or organization name as a prefix for the submodule
    name.

    一个经典的submodule的文本布局如下:

     submodule <module-name> {
    
         <yang-version statement>
    
         // module identification
         <belongs-to statement>
    
         // linkage statements
         <import statements>
         <include statements>
    
         // meta information
         <organization statement>
         <contact statement>
         <description statement>
         <reference statement>
    
         // revision history
         <revision statements>
    
         // module definitions
         <other statements>
     }
    

    7.2.1 submodule的substatements

                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | anyxml       | 7.10    | 0..n        |
                 | augment      | 7.15    | 0..n        |
               * | belongs-to   | 7.2.2   | 1           | 
                 | 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        |
                 | notification | 7.14    | 0..n        |
                 | organization | 7.1.7   | 0..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相比,多了一个belongs-to,少了一个prefix。

    7.2.2 belongs-to声明

    “belongs-to”声明指定了submodule所属的module。其参数是module名字。

    一个submodule MUST 只能被它所属的module,或者被它所属的module的其它submodules包含。

    “belongs-to”声明有一个必须出现的“prefix”声明,该声明指定了所属的module的prefix。在本地submodule中的所有定义,以及它所包含的submodules都能通过这个prefix访问。

                      The belongs-to's Substatements
    
                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | prefix       | 7.1.4   | 1           |
                 +--------------+---------+-------------+
    

    7.2.3 使用用例

     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...
     }
    

    7.3 typedef声明

    根据Section 5.5中的规则,“typedef”声明定义了一个新的type,能够在module内部,包含该module的modules或submodules,以及导入该module的其它modules使用。新的type称为“derived type”(派生类型),被派生的类型称为“base type”(基本类型)。所有的派生类型都能最重追溯到YANG的内置类型。

    “typedef”声明的参数是一个identifier,该id就是新定义的类型的名字,其后面 MUST 跟着包含typedef详细信息的一块substatements。

    这个type的名字 MUST NOT 是YANG的内置类型。如果typedef定义在YANG module或submodule的top level,则其名字 MUST 在整个module中保持唯一。

    7.3.1 typedef的substatements

                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | default      | 7.3.4   | 0..1        |
                 | description  | 7.19.3  | 0..1        |
                 | reference    | 7.19.4  | 0..1        |
                 | status       | 7.19.2  | 0..1        |
                 | type         | 7.3.2   | 1           |
                 | units        | 7.3.3   | 0..1        |
                 +--------------+---------+-------------+
    

    7.3.2 typedef的type声明

    “type”声明 MSUT 出现在typedef中,定义了新定义type所派生的基本类型。可见Section 7.4。

    7.3.3 units声明

    “units”声明是可选的,其内容是一个字符串,包含了和这个type相关的units的文本定义。

    7.3.4 typedef的default声明

    “default”声明的参数是新的type的默认值。

    “default”声明的值 MUST 是有效的。

    如果base type有一个默认值,新的派生类型没有指定新的默认值,则base type的默认值也是新的派生类型的默认值。

    如果这个type的默认值,在派生类型或者leaf的定义中,根据相关restrictions,是无效的,则派生类型或leaf定义就 MUST 指定一个新的默认值,以匹配restrictions。

    7.3.5 使用用例

     typedef listen-ipv4-address {
         type inet:ipv4-address;
         default "0.0.0.0";
     }
    

    7.4 type声明

    “type”声明的参数是YANG的内置类型(见Section 9)或者派生类型(见Section 7.3),后面跟着可选的一块substatements,用于进一步对该type施加限制(restrictions)。

    所有内置类型能够使用的restriction声明取决于被限定的类型。

    7.4.1 type的substatements

               +------------------+---------+-------------+
               | substatement     | section | cardinality |
               +------------------+---------+-------------+
               | bit              | 9.7.4   | 0..n        |
               | enum             | 9.6.4   | 0..n        |
               | length           | 9.4.4   | 0..1        |
               | path             | 9.9.2   | 0..1        |
               | pattern          | 9.4.6   | 0..n        |
               | range            | 9.2.4   | 0..1        |
               | require-instance | 9.13.2  | 0..1        |
               | type             | 7.4     | 0..n        |
               +------------------+---------+-------------+
    

    没清楚这里使用type有什么意义?需要例子。

    7.5 constainer声明

    “container”声明被用来定义一个schema tree中包含的内部数据节点(interior data node)。它有一个参数,是一个identifier,后面跟着一块描述进详细信息的substatements。

    一个container节点没有一个值,但是在data tree中有一个列表的子节点。子节点都定义在container的substatements中。

    7.5.1 Containers with Presence

    YANG支持两种风格的containers,一种仅仅用于组织data nodes的垂直结构,一种出现在configuration中,有明确的意义。

    第一种风格中,container本身没有任何意义,它的存在仅仅是为了包含子节点。这是默认的风格。

    比如,同步光网络(SONET)的scrambling options的集合能被放到一个名为“scrambling”的container中,以增强配置结构的层次化,将这些节点整合到一起。这个“scrambling”节点本身没有意义,所以在它变成空的的时候可以移除该节点。

    在第二种风格中,container本身就是配置型数据(configuration)data,表示配置型数据的一个简单bit。The container acts as both a configuration knob and a means of organizing related configuration. 这些containers的创建和删除操作都必须是明确无误的。

    YANG称这种风格的container为一个“presence container”,这表示要使用“presence”声明,作为它的

    比如,一个“ssh”的container可能会启动使用ssh方式将日志写进设备的能力,不过也能包含任何和ssh相关的configuration knobs,比如连接速率和重试次数限制。

    “presence”声明(见Section 7.5.5)用来在data tree中给container的存在以语义。

    说这么多,都不如一个demo来的实在。真的是没看懂啊。

    7.5.2 container的substatements

                 +--------------+---------+-------------+
                 | 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        |
                 | leaf         | 7.6     | 0..n        |
                 | leaf-list    | 7.7     | 0..n        |
                 | list         | 7.8     | 0..n        |
                 | must         | 7.5.3   | 0..n        |
                 | presence     | 7.5.5   | 0..1        |
                 | reference    | 7.19.4  | 0..1        |
                 | status       | 7.19.2  | 0..1        |
                 | typedef      | 7.3     | 0..n        |
                 | uses         | 7.12    | 0..n        |
                 | when         | 7.19.5  | 0..1        |
                 +--------------+---------+-------------+
    

    7.5.3 must声明

    “must”声明是可选的,其参数是一个字符串包含了一个XPath表达式(见Section 6.4)。它被用来正式声明有效数据上的约束。约束根据Section 8的规则执行。

    当一个datastore可用时,所有的“must”约束都会对data tree中的每个data node,对于使用默认值的所有leafs(见Section 7.6.1)进行概念上的评估。如果一个data node在data tree中并不存在,并且没有一个默认值,则它的“must”声明不会被评估。(When a datastore is validated, all “must” constraints are conceptually evaluated once for each data node in the data tree, and for all leafs with default values in use (see Section 7.6.1). If a data node does not exist in the data tree, and it does not have a default value, its “must” statements are not evaluated.

    所有这样的约束 MUST 评估为true,这样data才是有效的。

    XPath表达式在下述的上下文,以及Section 6.4.1的定义中也要进行概念上的评估(conceptually evaluated):

    • The context node is the node in the data tree for which the “must” statement is defined.
    • The accessible tree is made up of all nodes in the data tree, and all leafs with default values in use (see Section 7.6.1).

    可访问的tree取决于context node:

    • If the context node represents configuration, the tree is the data in the NETCONF datastore where the context node exists. The XPath root node has all top-level configuration data nodes in all modules as children.
    • If the context node represents state data, the tree is all state data on the device, and the datastore. The XPath root node has all top-level data nodes in all modules as children.
    • If the context node represents notification content, the tree is the notification XML instance document. The XPath root node has the element representing the notification being defined as the only child.
    • If the context node represents RPC input parameters, the tree is the RPC XML instance document. The XPath root node has the element representing the RPC operation being defined as the only child.
    • If the context node represents RPC output parameters, the tree is the RPC reply instance document. The XPath root node has the elements representing the RPC output parameters as children.

    使用标准的XPath规则评估的XPath表达式的结果会被转化为一个boolean值。

    Note that since all leaf values in the data tree are conceptually stored in their canonical form (see Sections 7.6 and 7.7), any XPath comparisons are done on the canonical value.

    Also note that the XPath expression is conceptually evaluated. This means that an implementation does not have to use an XPath evaluator on the device. How the evaluation is done in practice is an implementation decision.

    7.5.4 must的substatements

                 +---------------+---------+-------------+
                 | substatement  | section | cardinality |
                 +---------------+---------+-------------+
                 | description   | 7.19.3  | 0..1        |
                 | error-app-tag | 7.5.4.2 | 0..1        |
                 | error-message | 7.5.4.1 | 0..1        |
                 | reference     | 7.19.4  | 0..1        |
                 +---------------+---------+-------------+
    
    7.5.4.1 error-message声明

    “error-message”声明是可选的,其参数是一个字符串。如果约束的评估结果为false,这个字符串会被放在的中。

    7.5.4.2 error-app-tag声明

    “error-app-tag”声明是可选的,其参数是一个字符串。如果约束的评估结果为false,这个字符串会被放在的中。

    7.5.4.3 must和error-message的使用用例
     container interface {
         leaf ifType {
             type enumeration {
                 enum ethernet;
                 enum atm;
             }
         }
         leaf ifMTU {
             type uint32;
         }
         must "ifType != 'ethernet' or " +
              "(ifType = 'ethernet' and ifMTU = 1500)" {
             error-message "An ethernet MTU must be 1500";
         }
         must "ifType != 'atm' or " +
              "(ifType = 'atm' and ifMTU <= 17966 and ifMTU >= 64)" {
             error-message "An atm MTU must be  64 .. 17966";
         }
     }
    

    7.5.5 presence声明

    “presence”声明指定了在data tree中一个container的presence的含义。它的参数是一个字符串,包含了node的presence means的文本描述。

    如果一个container有“presence”声明,则存在于data tree中的该container就是有意义的。否则,该container就是第一类型的container,仅仅用于将数据结构化,本身并不携带任何意义。

    更多信息可见Section 7.5.1。

    简单来说,这个声明存在的意义就是用来判别container是第一类还是第二类的。不过没有见到哪个文档里有具体的实现啊。

    7.5.6 container的child node声明

    在一个container中,child nodes可以是“container”,“leaf”,“list”,“leaf-list”,“uses”,“choice”,以及“anyxml”声明。

    7.5.7 XML 映射规则

    一个container节点被编码为一个XML element。这个element的local name就是container的identifier,它的namespace就是module的XML namespace(见Section 7.1.3)。

    container的child nodes被编码为container element的subelements。如果container定义了RPC input或output参数,这些subelements被编码的顺序和它们在“container”声明中定义的顺序一致。否则,subelements的编码顺序随意。

    一个NETCONF服务端在回复一个或请求的时候,如果container node没有“presence”声明并且没有child nodes存在,则 MAY 不会发送这个container element作为回复。因此,一个发送或后获得回复的客户端,必须能够处理一种情况,那就是在XML中没有不包含“presence”声明的container node。

    涉及到NETCONF的时候就一脸蒙逼。

    7.5.8 NETCONF 操作

    containers可以通过在中使用“operation”属性(见【RFC4741】 Section 7.2)被创建,删除,替换和修改。

    如果一个container没有包含“presence”声明,并且最后一个child node都被删除了,则NETCONF服务端 MAY 删除这个container。当一个NETCONF服务端处理一个请求的时候,container node的处理流程如下:

    • 如果operation是“merge”或者“replace”,当该node不存在时则会被创建。
    • 如果operation是“create”,当该node不存在时会被创建。如果该node已经存在了,则会返回一个“data-exists”错误。
    • 如果operation是“delete”,当该node存在时会被哦删除。如果该node不存在,则会返回“data-missing”错误。

    7.5.9 使用用例

    给出下面的container的定义:

     container system {
         description "Contains various system parameters";
         container services {
             description "Configure externally available services";
             container "ssh" {
                 presence "Enables SSH";
                 description "SSH service specific configuration";
                 // more leafs, containers and stuff here...
             }
         }
     }
    

    对应的XML实例为:

     <system>
       <services>
         <ssh/>
       </services>
     </system>
    

    由于 element出现了,所以ssh是enabled的。

    使用删除一个container:

     <rpc message-id="101"
          xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
       <edit-config>
         <target>
           <running/>
         </target>
         <config>
           <system xmlns="http://example.com/schema/config">
             <services>
               <ssh nc:operation="delete"/>
             </services>
           </system>
         </config>
       </edit-config>
     </rpc>     
    

    7.6 leaf声明

    “leaf”声明被用来在schema tree中定义一个leaf node。它只有一个参数,是identifier,后面跟着详细描述该leaf信息的一块substatements。

    一个leaf node有一个值,但是在data tree中没有child nodes。概念上将,data tree中的值总是以canonical form存在的(见Section 9.1)。

    在data tree中存在0个或者1个leaf node。

    “leaf”声明被用来定义一个特定类型的标量变量。

    7.6.1 leaf的默认值(default value)

    一个leaf的默认值是当在data tree中没有该leaf存在时,服务端采用的值。默认值的采用取决于schema tree中离该leaf最近的带有“presence” 的container的祖先节点:

    • 如果在schema tree中没有这样的祖先节点,则默认值 MUST 被使用
    • 否则,如果这个祖先节点是一个case node,则如果data tree中有任何该case的node存在,或者这个case node就是choice的默认case,并且data tree中没有任何其它的case存在,这样一来就必须使用默认值。
    • 再否则,如果在data tree中有这样的祖先节点存在,则默认值 MUST 被使用。

    表示完全看不懂上面说了些啥?并且不明白为什么这么设置。

    在这些例子中,默认值都要被使用。

    当默认值被使用的时候,服务端 MUST 表现得好像这个值为默认值的这个leaf node就存在于data tree中一样。

    如果一个leaf有一个“default”声明,则该leaf的默认值就是“default”声明指定的值。否则,如果leaf的type有一个默认的值,并且该leaf不是强制出现(mandatory)的,则该leaf的默认值就是该type的默认值。在所有其它情况下,这个leaf没有一个默认值。

    7.6.2 leaf的substatements

                 +--------------+---------+-------------+
                 | 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        |
                 +--------------+---------+-------------+
    

    7.6.3 leaf的type声明

    “type”声明, MUST要出现,有一个参数,是当前已有的内置或者佩声类型。在这个type上有可选的substatements指定了相关的restrictions。可见Section 7.4。

    7.6.4 leaf的default声明

    “default”声明,是可选的,其参数是一个字符串,包含了leaf的默认值。

    “default”声明的值 MUST是有效可用的,不能违背对应type的规则。

    如果“mantory”为true,则“default”声明 MUST NOT 不能出现在nodes中。

    7.6.5 leaf的mandatory声明

    The “mandatory” statement, which is optional, takes as an argument
    the string “true” or “false”, and puts a constraint on valid data.
    If not specified, the default is “false”.

    If “mandatory” is “true”, the behavior of the constraint depends on
    the type of the leaf’s closest ancestor node in the schema tree that
    is not a non-presence container (see Section 7.5.1):

    o If no such ancestor exists in the schema tree, the leaf MUST
    exist.

    o Otherwise, if this ancestor is a case node, the leaf MUST exist if
    any node from the case exists in the data tree.

    o Otherwise, the leaf MUST exist if the ancestor node exists in the
    data tree.

    This constraint is enforced according to the rules in Section 8.

    7.6.6 XML映射规则

      A leaf node is encoded as an XML element.  The element's local name
    

    is the leaf’s identifier, and its namespace is the module’s XML
    namespace (see Section 7.1.3).

    The value of the leaf node is encoded to XML according to the type,
    and sent as character data in the element.

    A NETCONF server that replies to a or request MAY
    choose not to send the leaf element if its value is the default
    value. Thus, a client that receives an for a or
    request, MUST be prepared to handle the case that a leaf
    node with a default value is not present in the XML. In this case,
    the value used by the server is known to be the default value.

    See Section 7.6.8 for an example.

    7.6.7 NETCONF Operations

    When a NETCONF server processes an request, the
    elements of procedure for the leaf node are:

      If the operation is "merge" or "replace", the node is created if
      it does not exist, and its value is set to the value found in the
      XML RPC data.
    
      If the operation is "create", the node is created if it does not
      exist.  If the node already exists, a "data-exists" error is
      returned.
    
      If the operation is "delete", the node is deleted if it exists.
      If the node does not exist, a "data-missing" error is returned.
    

    7.6.8 使用实例

    给定下面的“leaf”声明,放到之前定义的 “ssh”的container中(可见Section 7.5.9):

     leaf port {
         type inet:port-number;
         default 22;
         description "The port to which the SSH server listens"
     }      
    

    对应的XML实例为:

     <port>2022</port>
    

    在中设置该leaf的值:

     <rpc message-id="101"
          xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
       <edit-config>
         <target>
           <running/>
         </target>
         <config>
           <system xmlns="http://example.com/schema/config">
             <services>
               <ssh>
                 <port>2022</port>
               </ssh>
             </services>
           </system>
         </config>
       </edit-config>
     </rpc>
    

    7.7 leaf-list声明

    “leaf”声明是被用来定义一个简单的特定类型的标量变量,而“leaf-list”声明被用来定义特定类型的一个数组。“leaf-list”声明有一个参数,是一个identifier,后面跟着描述具体内容的一块substatements。

    “leaf-list”的值 MUST 是唯一的。

    概念上来讲,data tree中的值总是以canonical form存在的(见Section 9.1)。

    如果“leaf-list”引用的type有默认值,默认值对leaf-list产生什么影响(If the type referenced by the leaf-list has a default value, it has no effect in the leaf-list.)。

    7.7.1 排序

    对于“list”和“leaf-list”声明,YANG支持两种风格的排序方式。在很多lists中,为了使被排列的列表项不影响列表配置的具体实现,设备能够以任何合理的顺序给list的列表项进行排序。不过在“description”中可能会有关于排序的建议。YANG称这种风格为“system ordered”,这种排序的声明为“ordered-by system”。

    比如,有时候为了对到来的流量进行过滤,防火墙的过滤条件列表项的顺序就变得有用。用户可能需要决定丢弃所有TCP流量的过滤项是放在允许信任接口流量通过的过滤项之前还是之后。这时候对于列表的排序就至关重要了。

    YANG为NETCONF的操作提供了丰富的特性集以便列表能够以用户规定的方式进行排序。列表项可能会被插入,或重新排列到列表的第一项或最后一项,或者放到某一个特定列表项的前面或者后面。

    “ordered-by”声明在Section 7.7.5 中有所包含。

    7.7.2 leaf-list的substatements

                 +--------------+---------+-------------+
                 | 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        |
                 +--------------+---------+-------------+
    

    7.7.3 min-elements声明

    “min-elements”声明,是可选的,取值为一个非负的整型,是对有效列表项的一个约束。一个可用的“leaf-list”或者“list” MUST 至少有min-elements个列表项。

    如果该声明不存在,则默认为0。

    The behavior of the constraint depends on the type of the leaf-list’s
    or list’s closest ancestor node in the schema tree that is not a non-
    presence container (see Section 7.5.1):

    o If this ancestor is a case node, the constraint is enforced if any
    other node from the case exists.

    o Otherwise, it is enforced if the ancestor node exists.

    The constraint is further enforced according to the rules in
    Section 8.

    7.7.4 max-elements声明

    The “max-elements” statement, which is optional, takes as an argument
    a positive integer or the string “unbounded”, which puts a constraint
    on valid list entries. A valid leaf-list or list always has at most
    max-elements entries.

    If no “max-elements” statement is present, it defaults to
    “unbounded”.

    The “max-elements” constraint is enforced according to the rules in
    Section 8.

    7.7.5 ordered-by声明

    “ordered-by”声明定义了列表中列表项的顺序是用户定义还是系统自定义。其参数是“system”和“user”中的一个。如果该声明没有出现,默认值是“system”。

    如果列表表达的是state date,RPC output parameters,或者notification content,则这个声明会被忽略,因为对以上三种数据,都没有排序的必要。

    更多信息可见Section 7.7.1

    7.7.5.1 ordered-by system

    The entries in the list are sorted according to an unspecified order.
    Thus, an implementation is free to sort the entries in the most
    appropriate order. An implementation SHOULD use the same order for
    the same data, regardless of how the data were created. Using a
    deterministic order will make comparisons possible using simple tools
    like “diff”.

    This is the default order.

    7.7.5.2 ordered-by user

    列表项的排序是用户通过中的特殊XML属性控制的。可见Section 7.7.7

    7.7.6 XML映射规则

    A leaf-list node is encoded as a series of XML elements. Each
    element’s local name is the leaf-list’s identifier, and its namespace
    is the module’s XML namespace (see Section 7.1.3).

    The value of each leaf-list entry is encoded to XML according to the
    type, and sent as character data in the element.

    The XML elements representing leaf-list entries MUST appear in the
    order specified by the user if the leaf-list is “ordered-by user”;
    otherwise, the order is implementation-dependent. The XML elements
    representing leaf-list entries MAY be interleaved with other sibling
    elements, unless the leaf-list defines RPC input or output
    parameters.

    See Section 7.7.8 for an example.

    7.7.7 NETCONF 操作

    Leaf-list entries can be created and deleted, but not modified,
    through , by using the “operation” attribute in the
    leaf-list entry’s XML element.

    In an “ordered-by user” leaf-list, the attributes “insert” and
    “value” in the YANG XML namespace (Section 5.3.1) can be used to
    control where in the leaf-list the entry is inserted. These can be
    used during “create” operations to insert a new leaf-list entry, or
    during “merge” or “replace” operations to insert a new leaf-list
    entry or move an existing one.

    The “insert” attribute can take the values “first”, “last”, “before”,
    and “after”. If the value is “before” or “after”, the “value”
    attribute MUST also be used to specify an existing entry in the leaf-
    list.

    If no “insert” attribute is present in the “create” operation, it
    defaults to “last”.

    If several entries in an “ordered-by user” leaf-list are modified in
    the same request, the entries are modified one at the
    time, in the order of the XML elements in the request.

    In a , or an with a “replace” operation
    that covers the entire leaf-list, the leaf-list order is the same as
    the order of the XML elements in the request.

    When a NETCONF server processes an request, the
    elements of procedure for a leaf-list node are:

      If the operation is "merge" or "replace", the leaf-list entry is
      created if it does not exist.
    
      If the operation is "create", the leaf-list entry is created if it
      does not exist.  If the leaf-list entry already exists, a
      "data-exists" error is returned.
    
      If the operation is "delete", the entry is deleted from the leaf-
      list if it exists.  If the leaf-list entry does not exist, a
      "data-missing" error is returned.   
    

    7.7.8 使用用例

     leaf-list allow-user  {
         type string;
         description "A list of user name patterns to allow";
     }
    

    对应的XML实例:

     <allow-user>alice</allow-user>
     <allow-user>bob</allow-user>
    

    为了在列表中增加一个新元素,使用中的操作“merge”:

     <rpc message-id="101"
          xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
       <edit-config>
         <target>
           <running/>
         </target>
         <config>
           <system xmlns="http://example.com/schema/config">
             <services>
               <ssh>
                 <allow-user>eric</allow-user>
               </ssh>
             </services>
           </system>
         </config>
       </edit-config>
     </rpc>
    

    给定下面的用户排序的例子:

     leaf-list cipher  {
         type string;
         ordered-by user;
         description "A list of ciphers";
     }                
    

    下面的语句是要在“3des-cbc”后面插入一条新的cipher “blowfish-cbc”:

     <rpc message-id="101"
          xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:yang="urn:ietf:params:xml:ns:yang:1">
       <edit-config>
         <target>
           <running/>
         </target>
         <config>
           <system xmlns="http://example.com/schema/config">
             <services>
               <ssh>
                 <cipher nc:operation="create"
                         yang:insert="after"
                         yang:value="3des-cbc">blowfish-cbc</cipher>
               </ssh>
             </services>
           </system>
         </config>
       </edit-config>
     </rpc>
    

    7.8 list声明

    “list”声明被用来定义一个schema tree中的内部数据节点(interior data node)。一个list node在data tree中可能有多个实例存在。每个这样的实例都被认为是一个列表项。“list”声明有一个参数,是identifier,后面跟着描述更详细信息的一块substatements。

    一个列表项是由该列表的keys的值唯一指定的,前提是keys存在。

    7.8.1 list的substatements

                 +--------------+---------+-------------+
                 | 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        |
                 +--------------+---------+-------------+
    

    7.8.2 list的key声明

    “key”声明,如果该list表示的是configuration信息,则 MUST 存在;其他情况下,则MAY 存在。有一个字符串的参数,该字符串是一个用空格符作为分隔符的这个list中的leaf的identifiers的列表。在key中,一个leaf的identifier MUST NOT 出现超过一次。每个这样的leaf identifier MUST 是该list的child leaf中的一个。这个leafs能直接在list的substatements中定义,也可以在list中的groupings里使用。

    在key中指定的所有leafs的值的组合唯一确定了一个列表项(感觉有点类似于数据库中的联合主键)。当一个列表项被创建时,所有的key leafs都 MUST 被赋值。这样一来,在key leafs中的任何默认值都会被忽略。key leafs中的任何mandatory statement都会被忽略。

    不太明白啥意思。附上原文:Thus, any default values in the key leafs or their types are ignored. It also implies that any mandatory statement in the key leafs are ignored.

    作为key的一部分的一个leaf能够是任何内置类型或者派生类型,但是 MUST NOT 是内置类型“empty”。

    All key leafs in a list MUST have the same value for their “config” as the list itself.

    key的字符串的语法是Section 12中的“key-arg”规则定义的。

    7.8.3 list的unique声明

    “unique”声明被用来对有效的列表项施加约束的。它有一个参数,是一个字符串。该字符串中包含了schema node identifiers的以空格为分隔符的列表,这些ids MUST 是descendant form的形式(见Section 12中的“descendant-schema-nodeid”规则)。每个这样的schema node identifier MUST 指向一个leaf。

    如果被引用的leafs中有一个是configuration data,则所有被引用的leafs都 MUST 表示configuration data。

    “unique”约束指定:所有在参数字符串中指定的leafs的实例的值,包括那些使用默认值的leafs,都 MUST 在所有列表项实例中保证唯一。这个约束根据Section 8的规则强制执行。

    “unique”字符串语法由Section 12中的“unique-arg”语法正式定义。

    7.8.3.1 使用用例

    假设有下面的list定义:

     list server {
         key "name";
         unique "ip port";
         leaf name {
             type string;
         }
         leaf ip {
             type inet:ip-address;
         }
         leaf port {
             type inet:port-number;
         }
     }
    

    则下面两个configuration是无效的:

     <server>
       <name>smtp</name>
       <ip>192.0.2.1</ip>
       <port>25</port>
     </server>
    
     <server>
       <name>http</name>
       <ip>192.0.2.1</ip>
       <port>25</port>
     </server>
    

    下面的configuration是有效的,因为“http”和“ftp”的list表项没有实现所有被unique引用的leafs,因此在“unique”约束执行检查的时候不会被约束掉:

     <server>
       <name>smtp</name>
       <ip>192.0.2.1</ip>
       <port>25</port>
     </server>
    
     <server>
       <name>http</name>
       <ip>192.0.2.1</ip>
     </server>
    
     <server>
       <name>ftp</name>
       <ip>192.0.2.1</ip>
     </server>
    

    7.8.4 list的child node statements

    list的child nodes可以是”container”, “leaf”, “list”, “leaf-list”, “uses”,
    “choice”, 以及 “anyxml”。

    7.8.5 XML映射规则

    A list is encoded as a series of XML elements, one for each entry in
    the list. Each element’s local name is the list’s identifier, and
    its namespace is the module’s XML namespace (see Section 7.1.3).

    The list’s key nodes are encoded as subelements to the list’s
    identifier element, in the same order as they are defined within the
    “key” statement.

    The rest of the list’s child nodes are encoded as subelements to the
    list element, after the keys. If the list defines RPC input or
    output parameters, the subelements are encoded in the same order as
    they are defined within the “list” statement. Otherwise, the
    subelements are encoded in any order.

    The XML elements representing list entries MUST appear in the order
    specified by the user if the list is “ordered-by user”, otherwise the
    order is implementation-dependent. The XML elements representing
    list entries MAY be interleaved with other sibling elements, unless
    the list defines RPC input or output parameters.

    7.8.6 NETCONF 操作

    List entries can be created, deleted, replaced, and modified through
    , by using the “operation” attribute in the list’s XML
    element. In each case, the values of all keys are used to uniquely
    identify a list entry. If all keys are not specified for a list
    entry, a “missing-element” error is returned.

    In an “ordered-by user” list, the attributes “insert” and “key” in
    the YANG XML namespace (Section 5.3.1) can be used to control where
    in the list the entry is inserted. These can be used during “create”
    operations to insert a new list entry, or during “merge” or “replace”
    operations to insert a new list entry or move an existing one.

    The “insert” attribute can take the values “first”, “last”, “before”,
    and “after”. If the value is “before” or “after”, the “key”
    attribute MUST also be used, to specify an existing element in the
    list. The value of the “key” attribute is the key predicates of the
    full instance identifier (see Section 9.13) for the list entry.

    If no “insert” attribute is present in the “create” operation, it
    defaults to “last”.

    If several entries in an “ordered-by user” list are modified in the
    same request, the entries are modified one at the time,
    in the order of the XML elements in the request.

    In a , or an with a “replace” operation
    that covers the entire list, the list entry order is the same as the
    order of the XML elements in the request.

    When a NETCONF server processes an request, the
    elements of procedure for a list node are:

      If the operation is "merge" or "replace", the list entry is
      created if it does not exist.  If the list entry already exists
      and the "insert" and "key" attributes are present, the list entry
      is moved according to the values of the "insert" and "key"
      attributes.  If the list entry exists and the "insert" and "key"
      attributes are not present, the list entry is not moved.
    
      If the operation is "create", the list entry is created if it does
      not exist.  If the list entry already exists, a "data-exists"
      error is returned.
    
      If the operation is "delete", the entry is deleted from the list
      if it exists.  If the list entry does not exist, a "data-missing"
      error is returned.
    

    7.8.7 使用用例

    给定下面的一个list:

     list user {
         key "name";
         config true;
         description "This is a list of users in the system.";
    
         leaf name {
             type string;
         }
         leaf type {
             type string;
         }
         leaf full-name {
             type string;
         }
     }
    

    对应的XML实例:

     <user>
       <name>fred</name>
       <type>admin</type>
       <full-name>Fred Flintstone</full-name>
     </user>
    

    创建一个新用户“barney”:

         <rpc message-id="101"
              xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
              xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
           <edit-config>
             <target>
               <running/>
             </target>
             <config>
               <system xmlns="http://example.com/schema/config">
                 <user nc:operation="create">
                   <name>barney</name>
                   <type>admin</type>
                   <full-name>Barney Rubble</full-name>
                 </user>
               </system>
             </config>
           </edit-config>
         </rpc>

    改变“fred”的类型为“superuser”:

         <rpc message-id="101"
              xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
              xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
           <edit-config>
             <target>
               <running/>
             </target>
             <config>
               <system xmlns="http://example.com/schema/config">
                 <user>
                   <name>fred</name>
                   <type>superuser</type>
                 </user>
               </system>
             </config>
           </edit-config>
         </rpc>

    给定下面的ordered-by user list:

     list user {
         description "This is a list of users in the system.";
         ordered-by user;
         config true;
    
         key "name";
    
         leaf name {
             type string;
         }
         leaf type {
             type string;
         }
         leaf full-name {
             type string;
         }
     }
    

    下面的xml表示在用户“fred”后面插入一个新用户“barney”:

         <rpc message-id="101"
              xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
              xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
              xmlns:yang="urn:ietf:params:xml:ns:yang:1">
           <edit-config>
             <target>
               <running/>
             </target>
             <config>
               <system xmlns="http://example.com/schema/config"
                    xmlns:ex="http://example.com/schema/config">
                 <user nc:operation="create"
                       yang:insert="after"
                       yang:key="[ex:name='fred']">
                   <name>barney</name>
                   <type>admin</type>
                   <full-name>Barney Rubble</full-name>
                 </user>
               </system>
             </config>
           </edit-config>
         </rpc>     

    下面的语句是将用户“barney”移到用户“fred”前面:

         <rpc message-id="101"
              xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
              xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
              xmlns:yang="urn:ietf:params:xml:ns:yang:1">
           <edit-config>
             <target>
               <running/>
             </target>
             <config>
               <system xmlns="http://example.com/schema/config"
                    xmlns:ex="http://example.com/schema/config">
                 <user nc:operation="merge"
                       yang:insert="before"
                       yang:key="[ex:name='fred']">
                   <name>barney</name>
                 </user>
               </system>
             </config>
           </edit-config>
         </rpc>

    7.9 choice声明

    “choice”声明定义了可选项的一个集合,同时只能有其中的一个存在。其参数是一个identifier,后面跟着描述具体信息的一块substatements。这个identifier被用来在schema tree中标识这个choice node。choice node不会在data tree中存在。

    一个choice由多个branches组成,这些branches是用“case” substatement定义的。每个branch都包含多个child nodes。在这些branches中同时最多只能有其中一个branch的nodes能够存在。

    更多信息可见Section 8.3.2

    7.9.1 choice的substatements

                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | anyxml       | 7.10    | 0..n        |
                 | case         | 7.9.2   | 0..n        |
                 | config       | 7.19.1  | 0..1        |
                 | container    | 7.5     | 0..n        |
                 | default      | 7.9.3   | 0..1        |
                 | description  | 7.19.3  | 0..1        |
                 | if-feature   | 7.18.2  | 0..n        |
                 | leaf         | 7.6     | 0..n        |
                 | leaf-list    | 7.7     | 0..n        |
                 | list         | 7.8     | 0..n        |
                 | mandatory    | 7.9.4   | 0..1        |
                 | reference    | 7.19.4  | 0..1        |
                 | status       | 7.19.2  | 0..1        |
                 | when         | 7.19.5  | 0..1        |
                 +--------------+---------+-------------+
    

    7.9.2 choice的case声明

    “case”声明被用来定义choice的branches。它有一个参数,是identifier,后面跟着描述详细信息的一块substatements。

    这个identifier被用来在schema tree中标识这个case node。在data tree中不存在case node。

    在一个“case”声明中,其child nodes可以用“anyxml”,“choice”, “container”,“leaf”, “list”,“leaf-list”,以及“uses”声明。所有child nodes的identifiers都 MUST 在该choice的所有cases中保持唯一。例如,下面的定义就是非法的:

     choice interface-type {     // This example is illegal YANG
         case a {
             leaf ethernet { ... }
         }
         case b {
             container ethernet { ...}
         }
     }
    

    YANG中有一种简略的写法,当branch中包含单个的“anyxml”,“container”,“leaf”,“list”或者“leaf-list”声明的时候,“case”声明可以省略。这种情况下,这个case的identifier和其中的声明的identifier一样。下面是一个例子:

     choice interface-type {
         container ethernet { ... }
     }
    

    等价于:

     choice interface-type {
         case ethernet {
             container ethernet { ... }
         }
     }
    

    在一个choice中,case identifier MUST 是唯一的。

    7.9.2.1 case的substatements
                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | anyxml       | 7.10    | 0..n        |
                 | choice       | 7.9     | 0..n        |
                 | container    | 7.5     | 0..n        |
                 | description  | 7.19.3  | 0..1        |
                 | if-feature   | 7.18.2  | 0..n        |
                 | leaf         | 7.6     | 0..n        |
                 | leaf-list    | 7.7     | 0..n        |
                 | list         | 7.8     | 0..n        |
                 | reference    | 7.19.4  | 0..1        |
                 | status       | 7.19.2  | 0..1        |
                 | uses         | 7.12    | 0..n        |
                 | when         | 7.19.5  | 0..1        |
                 +--------------+---------+-------------+
    

    7.9.3 choice的default声明

    The “default” statement indicates if a case should be considered as
    the default if no child nodes from any of the choice’s cases exist.
    The argument is the identifier of the “case” statement. If the
    “default” statement is missing, there is no default case.

    当“mandatory”的值为true时,“default”声明 MUST 不能出现。

    The default case is only important when considering the default
    values of nodes under the cases. The default values for nodes under
    the default case are used if none of the nodes under any of the cases
    are present.

    There MUST NOT be any mandatory nodes (Section 3.1) directly under
    the default case.

    Default values for child nodes under a case are only used if one of
    the nodes under that case is present, or if that case is the default
    case. If none of the nodes under a case are present and the case is
    not the default case, the default values of the cases’ child nodes
    are ignored.

    In this example, the choice defaults to “interval”, and the default
    value will be used if none of “daily”, “time-of-day”, or “manual” are
    present. If “daily” is present, the default value for “time-of-day”
    will be used.

     container transfer {
         choice how {
             default interval;
             case interval {
                 leaf interval {
                     type uint16;
                     default 30;
                     units minutes;
                 }
             }
             case daily {
                 leaf daily {
                     type empty;
                 }
                 leaf time-of-day {
                     type string;
                     units 24-hour-clock;
                     default 1am;
                 }
             }
             case manual {
                 leaf manual {
                     type empty;
                 }
             }
         }
     }
    

    7.9.4 choice的mandatory声明

    “mandatory”声明,是可选的,其参数是值为“true”或“false”的string,作用是对有效的数据施加一种约束。如果取值为“true”,则说明choice的case branches中特定的某个branch中的至少一个node MUST 存在。

    如果没有指定,默认值是“false”。

    The behavior of the constraint depends on the type of the choice’s
    closest ancestor node in the schema tree which is not a non-presence
    container (see Section 7.5.1):

    o If this ancestor is a case node, the constraint is enforced if any
    other node from the case exists.

    o Otherwise, it is enforced if the ancestor node exists.

    The constraint is further enforced according to the rules in
    Section 8.

    7.9.5 XML映射规则

    choice和case nodes在XML中不可见。

    The child nodes of the selected “case” statement MUST be encoded in
    the same order as they are defined in the “case” statement if they
    are part of an RPC input or output parameter definition. Otherwise,
    the subelements are encoded in any order.

    7.9.6 NETCONF 操作

    Since only one of the choice’s cases can be valid at any time, the
    creation of a node from one case implicitly deletes all nodes from
    all other cases. If an operation creates a node from a
    case, the NETCONF server will delete any existing nodes that are
    defined in other cases inside the choice.

    7.9.7 使用用例

    给定下面的choice:

     container protocol {
         choice name {
             case a {
                 leaf udp {
                     type empty;
                 }
             }
             case b {
                 leaf tcp {
                    type empty;
                 }
             }
         }
     }
    

    对应的XML实例可以是:

     <protocol>
       <tcp/>
     </protocol>
    

    将protocol从tcp改成udp:

         <rpc message-id="101"
              xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
              xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
           <edit-config>
             <target>
               <running/>
             </target>
             <config>
               <system xmlns="http://example.com/schema/config">
                 <protocol>
                   <udp nc:operation="create"/>
                 </protocol>
               </system>
             </config>
           </edit-config>
         </rpc>

    7.10 anyxml声明

    “anyxml”声明定义了schema tree的一个内部节点(interior node)。它有一个参数,是一个identifier,后面跟着描述详细信息的一块substatements。

    “anyxml”声明被用来标识XML中未知的文本块。在XML上没有施加任何restrictions。这是相当有用的一点,比如说,在RPC的replies中。给出一个例子,在操作中的参数。

    一个anyxml节点不能被扩展(augmented),可见Section 7.15。

    由于对“anyxml”的使用会限制对内容的操控,所以 RECOMMENDED “anyxml”声明不要被用来表示configuration data。

    在data tree中,一个anyxml node只能存在于0个或1个实例中。

    上面这句话没明白,是说在data tree中,只能有一个anyxml的实现吗?原文如下:_An anyxml node exists in zero or one instances in the data tree.
    _

    7.10.1 anyxml的substatements

                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | config       | 7.19.1  | 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        |
                 | when         | 7.19.5  | 0..1        |
                 +--------------+---------+-------------+
    

    7.10.2 XML映射规则

    一个anyxml node会被编码为一个XML element。这个element的local name就是这个anyxml的identifier,它的namespace就是module的XML namespace。anyxml node的值会被编码为这个element的XML内容。

    需要明白,在编码中使用到的任何前缀对于每个实例来说都是本地有效的。这意味着,在不同的实现中,同一个XML会被编码为不同的东西。(Note that any prefixes used in the encoding are local to each instance encoding. This means that the same XML may be encoded differently by different implementations.

    7.10.3 NETCONF 操作

    一个anyxml node被认为是一块不透明的数据块(因为不知道里面什么内容,无法解析)。这个数据块只能整个被替换。

    在anyxml node的subelements中出现的任何“operation”属性都会被NETCONF服务端忽略,不作处理。

    When a NETCONF server processes an request, the
    elements of procedure for the anyxml node are:

      If the operation is "merge" or "replace", the node is created if
      it does not exist, and its value is set to the XML content of the
      anyxml node found in the XML RPC data.
    
      If the operation is "create", the node is created if it does not
      exist, and its value is set to the XML content of the anyxml node
      found in the XML RPC data.  If the node already exists, a
      "data-exists" error is returned.
    
      If the operation is "delete", the node is deleted if it exists.
      If the node does not exist, a "data-missing" error is returned.
    

    7.10.4 使用用例

    给定下面的“anyxml”声明:

     anyxml data;
    

    下面是同一个anyxml值的两种不同的编码:

     <data xmlns:if="http://example.com/ns/interface">
       <if:interface>
         <if:ifIndex>1</if:ifIndex>
       </if:interface>
     </data>
    
     <data>
       <interface xmlns="http://example.com/ns/interface">
         <ifIndex>1</ifIndex>
       </interface>
     </data>          
    

    7.11 grouping声明

    “grouping”声明被用来定义可重用的block of nodes,可能会在module内部被使用,在包含它的modules中使用,或者导入它的其它modules中被使用。它有一个参数,是一个identifier,后面跟着描述更详细信息的一块substatements。

    “grouping”声明不是一个data 定义的声明,在schema tree中不会定义任何nodes。

    一个grouping类似于常见编程语言中的“structure”或者“record”。

    一旦一个grouping被定义,它就能通过“uses”声明被引用(见Section 7.12)。一个grouping MUST NOT 引用它自己,也不能间接通过其它的groupings的引用链引用到自己。

    如果grouping定义在YANG module或submodule的top level,grouping的identifier就MUST 在module内是唯一的。

    grouping的作用不仅仅是一种文本替换机制,而且将某些nodes整合到了一个集合中。grouping中的identifiers会放到grouping定义的地方进行范围的界定,而不是放到其被使用的地方。而prefix mappings,type names,grouping names,以及extension usage会在“grouping”声明出现的垂直结构中进行评估。以extensions为例,这意味着extensions会被应用到grouping node,而不是uses node。

    没想明白为什么会放到grouping定义的地方进行scope的界定,如果这样的话,被引用的地方就有可能出现identifiers的冲突了吧?

    7.11.1 grouping的substatements

                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | anyxml       | 7.10    | 0..n        |
                 | choice       | 7.9     | 0..n        |
                 | container    | 7.5     | 0..n        |
                 | description  | 7.19.3  | 0..1        |
                 | grouping     | 7.11    | 0..n        |
                 | leaf         | 7.6     | 0..n        |
                 | leaf-list    | 7.7     | 0..n        |
                 | list         | 7.8     | 0..n        |
                 | reference    | 7.19.4  | 0..1        |
                 | status       | 7.19.2  | 0..1        |
                 | typedef      | 7.3     | 0..n        |
                 | uses         | 7.12    | 0..n        |
                 +--------------+---------+-------------+
    

    7.11.2 使用用例

     import ietf-inet-types {
         prefix "inet";
     }
    
     grouping endpoint {
         description "A reusable endpoint group.";
         leaf ip {
             type inet:ip-address;
         }
         leaf port {
             type inet:port-number;
         }
     }
    

    7.12 uses声明

    “uses”声明被用来引用一个“grouping”定义。它有一个参数,就是所引用的grouping的名字。

    “uses”的作用就是它所引用的grouping所包含的nodes会被复制到当前的schema tree中,并且后面会根据“refine”和“augment”声明而更新。

    暂时还不知道refine和augment是啥?

    在grouping中定义的identifiers不回绑定到一个在“grouping”声明内部没有出现的namespace,除非这个grouping的内容通过“uses”声明被增加到对应的schema tree中,这种情况下,它们就会被绑定到当前的module中。

    以防误解,附上原文:The identifiers defined in the grouping are not bound to a namespace until the contents of the grouping are added to the schema tree via a “uses” statement that does not appear inside a “grouping” statement, at which point they are bound to the namespace of the current module.

    7.12.1 uses的substatements

                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | augment      | 7.15    | 0..1        |
                 | description  | 7.19.3  | 0..1        |
                 | if-feature   | 7.18.2  | 0..n        |
                 | refine       | 7.12.2  | 0..1        |
                 | reference    | 7.19.4  | 0..1        |
                 | status       | 7.19.2  | 0..1        |
                 | when         | 7.19.5  | 0..1        |
                 +--------------+---------+-------------+
    

    7.12.2 refine声明

    在grouping中的每个node的某些属性都能通过“refine”声明refined。其参数是grouping中的某个node的identifier。这个node被称为这个refine的target node。如果grouping中的一个node在“refine”声明中没有作为target node出现,它就不会被refined,因此被引用的时候就按照它在grouping中定义的那样被引用。

    参数字符串是一个descendant schema node identifier(见Section 6.5)。

    可以进行下面的refinements:

    • 一个leaf或choice node可能通过“refine”获得一个默认值,或者本来就有一个默认值,被新的默认值替代了。
    • 任何node都能通过它获得应用场景下的“description”字符串。
    • 任何node都能通过它获得应用场景下的“reference”字符串。
    • 任何node都能通过它获得一个不同的“config”声明。
    • 一个leaf,anyxml,或者choice node都能通过它获得一个不同的“mandatory”声明。
    • 一个container node能通过它获得一个“presence”声明。表示一个container是否有实际意义
    • 一个leaf,leaf-list,list,container或anyxml node能通过它获得额外的“must”表达式。
    • 一个leaf-list或list node能通过它获得一个不同的“min-elements”或“max-elements”声明。

    refined这个词在词典中的意思是“精炼的”。不过给我的感觉更像是redefined或者modified。是为了适应grouping的使用场景对其做的一些修改。

    7.12.3 XML 映射规则

    在grouping中的每个node在编码时表现就像它是被内联进去的,即便它是其它XML namespace的另一个module中导入的。(简单来说,就按照C++里面的inline关键词理解就行了

    7.12.4 使用用例

    为了在其它module中定义的HTTP server中使用Section 7.11.2中定义的“endpoint” grouping,我们可以这么写:

     import acme-system {
         prefix "acme";
     }
    
     container http-server {
         leaf name {
             type string;
         }
         uses acme:endpoint;
     }
    

    对应的XML实例例子有:

         <http-server>
           <name>extern-web</name>
           <ip>192.0.2.1</ip>
           <port>80</port>
         </http-server>

    如果端口80应该是HTTP Server的默认端口,则可以这么写:

     container http-server {
         leaf name {
             type string;
         }
         uses acme:endpoint {
             refine port {
                 default 80;
             }
         }
     }
    

    如果我们要定义一个servers的list,其中每个server都将ip和port作为keys,我们可以这么写:

     list server {
         key "ip port";
         leaf name {
             type string;
         }
         uses acme:endpoint;
     }   
    

    下面是一个错误用例:

     container http-server {
         uses acme:endpoint;
         leaf ip {          // illegal - same identifier "ip" used twice
             type string;
         }
     }
    

    7.13 rpc声明

    “rpc”声明被用来定义一个NETCONF RPC操作。它有一个参数,是一个identifier,后面跟着描述详细信息的一块substatements。这个参数是RPC的名字,在XML中作为 element的element名字,as designated by the substitution group “rpcOperation” in RFC4741

    “rpc”声明在schema tree中定义了一个rpc node。在这个rpc node之下,也会定义两个schema node,一个名字叫“input”,一个叫“output”。node “input”和“output”都是定义在module的namespace中的。

    7.13.1 rpc的substatements

                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | description  | 7.19.3  | 0..1        |
                 | grouping     | 7.11    | 0..n        |
                 | if-feature   | 7.18.2  | 0..n        |
                 | input        | 7.13.2  | 0..1        |
                 | output       | 7.13.3  | 0..1        |
                 | reference    | 7.19.4  | 0..1        |
                 | status       | 7.19.2  | 0..1        |
                 | typedef      | 7.3     | 0..n        |
                 +--------------+---------+-------------+
    

    7.13.2 input声明

    “input”声明,是可选的,被用来定义RPC操作的输入参数。它没有参数。“input”的substatements直接定义在input node之下。

    如果在input tree中的一个leaf的“mandatory”声明的值为“true”,这个leaf MUST 在NETCONF RPC调用时出现,否则,服务端 MUST 返回一个“missing-element”的错误。

    如果一个在input tree中的leaf有默认值,则NETCONF服务器 MUST 在和如Section 7.6.1 相同的场景下使用这个值。在这些场景下,服务器 MUST 表现得好像在NETCONF RPC 调用中这个leaf本身就存在,并且其值为默认值。

    如果一个“config”声明出现在input tree中的任何node中,它都不会被处理。

    如果任何node的“when”声明的约束都被评估为false,则这个node MUST NOT 出现在input tree中。

    7.13.2.1 input的substatements
                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | anyxml       | 7.10    | 0..n        |
                 | choice       | 7.9     | 0..n        |
                 | container    | 7.5     | 0..n        |
                 | grouping     | 7.11    | 0..n        |
                 | leaf         | 7.6     | 0..n        |
                 | leaf-list    | 7.7     | 0..n        |
                 | list         | 7.8     | 0..n        |
                 | typedef      | 7.3     | 0..n        |
                 | uses         | 7.12    | 0..n        |
                 +--------------+---------+-------------+
    

    7.13.3 output声明

    “output”声明,是可选的,被用来定义RPC操作中的输出参数。它没有参数。“output”的substatements直接定义在其后。

    如果output tree中的一个leaf的“mandatory”声明的值为“true”,则这个leaf MUST 出现在NETCONF RPC reply中。

    如果output tree中的一个leaf有一个默认值,则NETCONF 客户端 MUST 在和Section 7.6.1描述的场景相同的情况下使用这个值。在这些情况下,客户端 MUST 表现得好像NETCONF RPC reply中本来就有这个leaf,并且其值就是默认值一样。

    如果一个“config”声明出现在output tree中的任何node中,则这个“config”声明不会被处理,会被忽略。

    如果任何node中有一个“when”声明约束,并且评估结果为false,则这个node MUST NOT 出现在output tree中。

    7.13.3.1 output的substatements
                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | anyxml       | 7.10    | 0..n        |
                 | choice       | 7.9     | 0..n        |
                 | container    | 7.5     | 0..n        |
                 | grouping     | 7.11    | 0..n        |
                 | leaf         | 7.6     | 0..n        |
                 | leaf-list    | 7.7     | 0..n        |
                 | list         | 7.8     | 0..n        |
                 | typedef      | 7.3     | 0..n        |
                 | uses         | 7.12    | 0..n        |
                 +--------------+---------+-------------+
    

    7.13.4 XML映射规则

    一个rpc node会被编码为【RFC4741】中定义的 element的child XML element。这个element的local name就是rpc的identifier,它的namespace就是rpc node所在module的XML namespace。

    input参数会被编码为rpc node的XML element的child XML elements,其排列顺序和“input” statement中定义的顺序一致。

    如果RPC 操作的调用成功,并且没有output参数返回,则会仅仅包含一个简单的 element。如果output参数有返回,它们会被编码为 element的child elements,其顺序和“output”声明中定义的顺序一致。

    7.13.5 使用用例

    下面的例子定义了一个RPC操作:

     module rock {
         namespace "http://example.net/rock";
         prefix "rock";
    
         rpc rock-the-house {
             input {
                 leaf zip-code {
                     type string;
                 }
             }
         }
     }
    

    对应的完整的rpc和rpc-reply的XML实例为:

     <rpc message-id="101"
          xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
       <rock-the-house xmlns="http://example.net/rock">
         <zip-code>27606-0100</zip-code>
       </rock-the-house>
     </rpc>
    
     <rpc-reply message-id="101"
                xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
       <ok/>
     </rpc-reply>
    

    7.14 notification声明

    “notification”声明被用来定义NETCONF的notification。它有一个参数,是一个identifier,后面跟着描述更详细信息的一块substatements。“notification”声明在schema tree中定义了一个notification node。

    如果notification tree中的一个leaf有值为true的“mandatory”声明,这个leaf MUST 在NETCONF的notification中出现。

    如果notification tree中的一个leaf有默认值,则NETCONF 客户端 MUST 在和Section 7.6.1描述的场景相同的情况下使用这个值。在这些情况下,客户端 MUST 表现得好像NETCONF notification中本来就有这个leaf,并且其值就是默认值一样。

    如果“config”声明出现在notification tree中的任何一个node中,则该声明会被忽略。

    7.14.1 notification的substatements

                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | anyxml       | 7.10    | 0..n        |
                 | choice       | 7.9     | 0..n        |
                 | container    | 7.5     | 0..n        |
                 | description  | 7.19.3  | 0..1        |
                 | grouping     | 7.11    | 0..n        |
                 | if-feature   | 7.18.2  | 0..n        |
                 | leaf         | 7.6     | 0..n        |
                 | leaf-list    | 7.7     | 0..n        |
                 | list         | 7.8     | 0..n        |
                 | reference    | 7.19.4  | 0..1        |
                 | status       | 7.19.2  | 0..1        |
                 | typedef      | 7.3     | 0..n        |
                 | uses         | 7.12    | 0..n        |
                 +--------------+---------+-------------+
    

    7.14.2 XML映射规则

    一个notification node会作为【RFC5277】中定义的NETCONF Event Notifications对应的 element的child XML element存在。这个element的local name就是notification的identifier,它的namespace就是notification所在的module的XML namespace。

    7.14.3 使用用例

    下面的例子定义了一个notification:

     module event {
    
         namespace "http://example.com/event";
         prefix "ev";
    
         notification event {
             leaf event-class {
                 type string;
             }
             anyxml reporting-entity;
             leaf severity {
                 type string;
             }
         }
     }
    

    完整的notification的对应的XML实例为:

     <notification
       xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
       <eventTime>2008-07-08T00:01:00Z</eventTime>
       <event xmlns="http://example.com/event">
         <event-class>fault</event-class>
         <reporting-entity>
           <card>Ethernet0</card>
         </reporting-entity>
         <severity>major</severity>
       </event>
     </notification>
    

    7.15 augment声明

    “augment”声明允许将一个module或submodule增加到另外一个module定义的schema tree中,或者增加到当前module以及它的submodules,或者增加到使用“uses”声明定义的grouping所引用的nodes中去。其参数是一个string,标识了一个node在schema tree中的位置。这个节点称为augment的target node。这个target node MUST container,list,choice,case,input,output或者notification node的一种。在该声明的substatements中定义的nodes会被augmented到target node中去。

    augment的参数字符串是一个schema node identifier(见Section 6.5)。如果“augment”声明是module或submodule的一个top level的node, MUST 在schema node identifier中使用absolute form(见Section 12中的“absolute-schema-nodeid”)。如果“augment”声明是“uses”声明的一个substatement,则 MUST 使用descendant form(见Section 12的“descendant-schema-nodeid”)。

    如果target node是一个containet,list,case,input,output或者notification node,则“container”,“leaf”,“list”,“leaf-list”,“uses”以及“choice”声明可以被用在“augment”声明中。

    如果target node是一个choice node, 则“case”声明,或者一个case的简写版的声明(见Section 7.9.2)可以被用在“augment”声明中。

    如果target node在另外一个module中,则由augmentation增加的nodes MUST NOT 是mandatory nodes(可见Section 3.1).(If the target node is in another module, then nodes added by the augmentation MUST NOT be mandatory nodes (see Section 3.1).

    The “augment” statement MUST NOT add multiple nodes with the same name from the same module to the target node.

    7.15.1 augment的substatements

                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | anyxml       | 7.10    | 0..n        |
                 | case         | 7.9.2   | 0..n        |
                 | choice       | 7.9     | 0..n        |
                 | container    | 7.5     | 0..n        |
                 | description  | 7.19.3  | 0..1        |
                 | if-feature   | 7.18.2  | 0..n        |
                 | leaf         | 7.6     | 0..n        |
                 | leaf-list    | 7.7     | 0..n        |
                 | list         | 7.8     | 0..n        |
                 | reference    | 7.19.4  | 0..1        |
                 | status       | 7.19.2  | 0..1        |
                 | uses         | 7.12    | 0..n        |
                 | when         | 7.19.5  | 0..1        |
                 +--------------+---------+-------------+
    

    status这个声明貌似还没见过呢。

    7.15.2 XML映射规则

    所有“augment”声明中定义的data nodes都会编码成“augment”被指定的那个module对应的XML namespace的XML elements。

    当一个node被augmented的时候,augmenting child nodes会被编码为augmented node的subelements,顺序任意。

    7.15.3 使用用例

    在namespace “http://example.com/schema/interfaces”中,我们有:

     container interfaces {
         list ifEntry {
             key "ifIndex";
    
             leaf ifIndex {
                 type uint32;
             }
             leaf ifDescr {
                 type string;
             }
             leaf ifType {
                 type iana:IfType;
             }
             leaf ifMtu {
                 type int32;
             }
         }
     }
    

    这里的ifType的类型为 “iana:IfType”。

    然后,在namespace “http://example.com/schema/ds0”中,我们有:

     import interface-module {
         prefix "if";
     }
     augment "/if:interfaces/if:ifEntry" {
         when "if:ifType='ds0'";
         leaf ds0ChannelNumber {
             type ChannelNumber;
         }
     }
    

    对应的XML实例是:

         <interfaces xmlns="http://example.com/schema/interfaces"
                     xmlns:ds0="http://example.com/schema/ds0">
           <ifEntry>
             <ifIndex>1</ifIndex>
             <ifDescr>Flintstone Inc Ethernet A562</ifDescr>
             <ifType>ethernetCsmacd</ifType>
             <ifMtu>1500</ifMtu>
           </ifEntry>
           <ifEntry>
             <ifIndex>2</ifIndex>
             <ifDescr>Flintstone Inc DS0</ifDescr>
             <ifType>ds0</ifType>
             <!-- 类型为ds0的时候,增加了ds0ChannelNumber -->
             <ds0:ds0ChannelNumber>1</ds0:ds0ChannelNumber>
           </ifEntry>
         </interfaces>     

    另外一个例子中,我们假设有一个在Section 7.9.7中定义的choice。下面的结构能被用来扩展其中的protocol的定义:

     augment /ex:system/ex:protocol/ex:name {
         case c {
             leaf smtp {
                 type empty;
             }
         }
     }
    

    对应的XML实例为:

         <ex:system>
           <ex:protocol>
             <ex:tcp/>
           </ex:protocol>
         </ex:system>

    或者:

         <ex:system>
           <ex:protocol>
             <other:smtp/>
           </ex:protocol>
         </ex:system>

    7.16 identity声明

    “identity”声明被用来定义一个新的,全局唯一的,抽象的,没有特定类型的identity。它的唯一目的就是对外宣示它的名字,语义以及存在。一个identity既能够从头开始定义,也能够从一个base identity处继承。identity的参数是一个identifier,就是这个identity的名字。后面跟着描述更具体信息的一块substatements。

    内置的数据类型“identityref”(见Section 9.10)能够在一个data model内部被用来引用identities。

    7.16.1 identity的substatements

                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | base         | 7.16.2  | 0..1        |
                 | description  | 7.19.3  | 0..1        |
                 | reference    | 7.19.4  | 0..1        |
                 | status       | 7.19.2  | 0..1        |
                 +--------------+---------+-------------+
    

    7.16.2 base声明

    “base”声明是可选的,其参数是一个已存在的identity的名字,本次定义的identity就是从它那里继承来的。如果“base”声明没有出现,则这个identity的定义就是从零开始的。

    如果在base的名字中有前缀,该前缀会指向定义这个identity的module,或者,如果该前缀正好是local module的前缀,则就指向本module。否则,MUST 指向当前的module或者一个被包含的submodule。

    local module 和 current module是有区别的,我日啊,之前一直以为是同样的东西。local表示本地,本地不一定只有current这一个module啊,也可以有其它module。

    由于submodules不能包含其父module,所以任何在module中定义的identities,如果需要被submodules引用,则 MUST 定义到某个submodule中去。submodules能够接着引用这个submodule去获取这个identity的定义。

    一个identity MUST NOT 引用自己,无论是直接的还是通过其它的identities形成的引用链进行的间接引用。

    7.1。3 使用用例

     module crypto-base {
         namespace "http://example.com/crypto-base";
         prefix "crypto";
    
         identity crypto-alg {
             description
                "Base identity from which all crypto algorithms
                 are derived.";
         }
     }
    
     module des {
         namespace "http://example.com/des";
         prefix "des";
    
         import "crypto-base" {
             prefix "crypto";
         }
    
         identity des {
             base "crypto:crypto-alg";
             description "DES crypto algorithm";
         }
    
         identity des3 {
             base "crypto:crypto-alg";
             description "Triple DES crypto algorithm";
         }
     }
    

    按照上面的描述来说,identity在schema tree中存在,在data tree中不存在了?

    7.17 extension声明

    “extension”声明允许在YANG语言中定义新的声明。这个新的声明的定义可以被其它modules导入和使用。

    该声明的参数是一个identifier,表示扩展的新keyword,后面必须跟一块描述详细扩展信息的substatements。“extension”声明的目标就是定义一个keyword,这样它才能被其它modules导入和使用。

    extension能像普通的YANG声明一样被使用,声明后面跟一个参数,后面还有可选的一块substatements。新声明的名字是该extension所在的module的前缀,跟上冒号(“:”),再跟上keyword,中间没有空白。extension的substatements是由extension定义的,使用了本标准以外的某些机制。在语法构成上,substatements MUST 是YANG声明,或者也是用“extension”声明定义的新声明。在extensions中使用的YANG声明 MUST 遵循Section 12中定义的语法上的规则。

    7.17.1 extension的substatements

                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | argument     | 7.17.2  | 0..1        |
                 | description  | 7.19.3  | 0..1        |
                 | reference    | 7.19.4  | 0..1        |
                 | status       | 7.19.2  | 0..1        |
                 +--------------+---------+-------------+
    

    7.17.2 argument声明

    “argument”声明,是可选的,是一个字符串,表示keyword的参数的名字。如果没有argument声明,则keyword在被使用的时候没有参数。

    argument的name在YIN mapping中被使用,在那里作为XML attribute或者element name,具体要取决于argument的“yin-element”声明。

    7.17.2.1 argument的substatements
                 +--------------+----------+-------------+
                 | substatement | section  | cardinality |
                 +--------------+----------+-------------+
                 | yin-element  | 7.17.2.2 | 0..1        |
                 +--------------+----------+-------------+
    
    7.17.2.2 yin-element声明

    “yin-element”声明,是可选的,其参数为“true”或者“false”的字符串。这个声明说明了是否将argument映射到YIN中的一个XML element,或者一个XML attribute(见Section 11)。

    如果该声明没有出现,默认值是“false”。

    7.17.3 使用用例

    首先,定义一个extension:

     module my-extensions {
       ...
    
       extension c-define {
         description
           "Takes as argument a name string.
           Makes the code generator use the given name in the
           #define.";
         argument "name";
       }
     }
    

    接着,使用这个extension:

     module my-interfaces {
       ...
       import my-extensions {
         prefix "myext";
       }
       ...
    
       container interfaces {
         ...
         myext:c-define "MY_INTERFACES";
       }
     }
    

    7.18 conformance-related声明

    这个小姐定义了和一致性(conformance)相关的声明,如Section 5.6中描述的一样。

    7.18.1 feature声明

    The “feature” statement is used to define a mechanism by which
    portions of the schema are marked as conditional. A feature name is
    defined that can later be referenced using the “if-feature” statement
    (see Section 7.18.2). Schema nodes tagged with a feature are ignored
    by the device unless the device supports the given feature. This
    allows portions of the YANG module to be conditional based on
    conditions on the device. The model can represent the abilities of
    the device within the model, giving a richer model that allows for
    differing device abilities and roles.

    The argument to the “feature” statement is the name of the new
    feature, and follows the rules for identifiers in Section 6.2. This
    name is used by the “if-feature” statement to tie the schema nodes to
    the feature.

    In this example, a feature called “local-storage” represents the
    ability for a device to store syslog messages on local storage of
    some sort. This feature is used to make the “local-storage-limit”
    leaf conditional on the presence of some sort of local storage. If
    the device does not report that it supports this feature, the
    “local-storage-limit” node is not supported.

     module syslog {
         ...
         feature local-storage {
             description
                 "This feature means the device supports local
                  storage (memory, flash or disk) 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.";
             }
         }
     }
    

    The “if-feature” statement can be used in many places within the YANG
    syntax. Definitions tagged with “if-feature” are ignored when the
    device does not support that feature.

    A feature MUST NOT reference itself, neither directly nor indirectly
    through a chain of other features.

    In order for a device to implement a feature that is dependent on any
    other features (i.e., the feature has one or more “if-feature” sub-
    statements), the device MUST also implement all the dependant
    features.

    7.18.1.1 feature的substatements
                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | description  | 7.19.3  | 0..1        |
                 | if-feature   | 7.18.2  | 0..n        |
                 | status       | 7.19.2  | 0..1        |
                 | reference    | 7.19.4  | 0..1        |
                 +--------------+---------+-------------+
    

    7.18.2 if-feature声明

    The “if-feature” statement makes its parent statement conditional.
    The argument is the name of a feature, as defined by a “feature”
    statement. The parent statement is implemented by servers that
    support this feature. If a prefix is present on the feature name, it
    refers to a feature defined in the module that was imported with that
    prefix, or the local module if the prefix matches the local module’s
    prefix. Otherwise, a feature with the matching name MUST be defined
    in the current module or an included submodule.

    Since submodules cannot include the parent module, any features in
    the module that need to be exposed to submodules MUST be defined in a
    submodule. Submodules can then include this submodule to find the
    definition of the feature.

    7.18.3 deviation声明

    The “deviation” statement defines a hierarchy of a module that the
    device does not implement faithfully. The argument is a string that
    identifies the node in the schema tree where a deviation from the
    module occurs. This node is called the deviation’s target node. The
    contents of the “deviation” statement give details about the
    deviation.

    The argument string is an absolute schema node identifier (see
    Section 6.5).

    Deviations define the way a device or class of devices deviate from a
    standard. This means that deviations MUST never be part of a
    published standard, since they are the mechanism for learning how
    implementations vary from the standards.

    Device deviations are strongly discouraged and MUST only be used as a
    last resort. Telling the application how a device fails to follow a
    standard is no substitute for implementing the standard correctly. A
    device that deviates from a module is not fully compliant with the
    module.

    However, in some cases, a particular device may not have the hardware
    or software ability to support parts of a standard module. When this
    occurs, the device makes a choice either to treat attempts to
    configure unsupported parts of the module as an error that is
    reported back to the unsuspecting application or ignore those
    incoming requests. Neither choice is acceptable.

    Instead, YANG allows devices to document portions of a base module
    that are not supported or supported but with different syntax, by
    using the “deviation” statement.

    7.18.3.1 deviation的substatements
                 +--------------+----------+-------------+
                 | substatement | section  | cardinality |
                 +--------------+----------+-------------+
                 | description  | 7.19.3   | 0..1        |
                 | deviate      | 7.18.3.2 | 1..n        |
                 | reference    | 7.19.4   | 0..1        |
                 +--------------+----------+-------------+
    
    7.18.3.2 divate声明

    The “deviate” statement defines how the device’s implementation of
    the target node deviates from its original definition. The argument
    is one of the strings “not-supported”, “add”, “replace”, or “delete”.

    The argument “not-supported” indicates that the target node is not
    implemented by this device.

    The argument “add” adds properties to the target node. The
    properties to add are identified by substatements to the “deviate”
    statement. If a property can only appear once, the property MUST NOT
    exist in the target node.

    The argument “replace” replaces properties of the target node. The
    properties to replace are identified by substatements to the
    “deviate” statement. The properties to replace MUST exist in the
    target node.

    The argument “delete” deletes properties from the target node. The
    properties to delete are identified by substatements to the “delete”
    statement. The substatement’s keyword MUST match a corresponding
    keyword in the target node, and the argument’s string MUST be equal
    to the corresponding keyword’s argument string in the target node.

                       The deviates's Substatements
    
                 +--------------+---------+-------------+
                 | substatement | section | cardinality |
                 +--------------+---------+-------------+
                 | config       | 7.19.1  | 0..1        |
                 | default      | 7.6.4   | 0..1        |
                 | mandatory    | 7.6.5   | 0..1        |
                 | max-elements | 7.7.4   | 0..1        |
                 | min-elements | 7.7.3   | 0..1        |
                 | must         | 7.5.3   | 0..n        |
                 | type         | 7.4     | 0..1        |
                 | unique       | 7.8.3   | 0..n        |
                 | units        | 7.3.3   | 0..1        |
                 +--------------+---------+-------------+
    
    7.18.3.3 使用用例

    In this example, the device is informing client applications that it
    does not support the “daytime” service in the style of RFC 867.

     deviation /base:system/base:daytime {
         deviate not-supported;
     }
    

    The following example sets a device-specific default value to a leaf
    that does not have a default value defined:

     deviation /base:system/base:user/base:type {
         deviate add {
             default "admin"; // new users are 'admin' by default
         }
     }
    

    In this example, the device limits the number of name servers to 3:

     deviation /base:system/base:name-server {
         deviate replace {
             max-elements 3;
         }
     }                 
    

    If the original definition is:

     container system {
         must "daytime or time";
         ...
     }
    

    a device might remove this must constraint by doing:

     deviation "/base:system" {
         deviate delete {
             must "daytime or time";
         }
     }
    

    7.19 通用的声明

    本小节定义了一些对其他声明来说都可以用的substatements。

    7.19.1 config声明

    “config”声明有一个参数,取值为“true”或者“false”。如果值为“true”,则表示本定义表示的是configuration。定义configuration的data nodes会是 request的回应的一部分,能够放在或者 request中发送出去。

    如果值为“false”,则表示本定义表示的是state data。定义state data的data nodes会是对 request的回应的一部分,单不会回应 request,并且不能放到或者 request中。

    如果没有指定“config”,则默认值和其parent schema node的“config”的值一样。如果parent node是一个“case” node,则这个值就和“case”node的parent “choice” noce相同。

    如果top node没有指定“config”声明,则默认值为“true”。

    如果一个node的“config”设置为“false”,则该节点的所有子节点都不能将“config”设置为“true”。

    7.19.2 status声明

    “status”声明的参数是一个字符串,是“current”,“deprecated”或者“obsolete”中的一个。

    • “current”意味着该定义在当前是有效的。
    • “deprecated”表示该定义已经被废弃,不过保证在暂时在后续的实现中支持该定义,以保证向前兼容。
    • “obsolete”意味着这个定义已经被废弃,并且 SHOULD NOT 被实现。

    如果没有指定status,则默认值为“current”。

    如果一个定义是“current”,则它 MUST NOT 在同一个module中引用“deprecated”或“obsolete”定义。

    如果一个定义是“deprecated”,则它 MUST NOT 在同一个module中引用“obsolete”定义。

    比如说,下面的例子就是非法的:

     typedef my-type {
       status deprecated;
       type int32;
     }
    
     leaf my-leaf {
       status current;
       type my-type; // illegal, since my-type is deprecated
     }
    

    7.19.3 description声明

    The “description” statement takes as an argument a string that
    contains a human-readable textual description of this definition.
    The text is provided in a language (or languages) chosen by the
    module developer; for the sake of interoperability, it is RECOMMENDED
    to choose a language that is widely understood among the community of
    network administrators who will use the module.

    7.19.4 reference声明

    “reference”声明有一个参数,是字符串,该参数被用来指定一个到外部文档的交叉引用,既可以是定义了相关管理信息的另一个module,也可以是能对本定义提供相关额外信息的一个文档。

    比如,定义了名为“uri” 的一个typedef,可以这么写:

     typedef uri {
       type string;
       reference
         "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax";
       ...
     }
    

    7.19.5 when声明

    “when”声明可以使它的parent data 定义声明变成有条件的。由其parent data定义声明所定义的node仅当该“when”声明提供的要求(condition)得到满足时才有可能是有效的。该声明的参数是一个XPath表达式(见Section 6.4),该表达式被用来精确描述这个条件(condition)。如果XPath表达式针对特定的实例被评估为“true”的话,则该parent data定义声明所定义的node就是有效的,反之亦然。

    更多信息可见Section 8.3.2。

    The XPath expression is conceptually evaluated in the following
    context, in addition to the definition in Section 6.4.1:

    o If the “when” statement is a child of an “augment” statement, then
    the context node is the augment’s target node in the data tree, if
    the target node is a data node. Otherwise, the context node is
    the closest ancestor node to the target node that is also a data
    node.

    o If the “when” statement is a child of a “uses”, “choice”, or
    “case” statement, then the context node is the closest ancestor
    node to the “uses”, “choice”, or “case” node that is also a data
    node.

    o If the “when” statement is a child of any other data definition
    statement, the context node is the data definition’s node in the
    data tree.

    o The accessible tree is made up of all nodes in the data tree, and
    all leafs with default values in use (see Section 7.6.1).

    The accessible tree depends on the context node:

    o If the context node represents configuration, the tree is the data
    in the NETCONF datastore where the context node exists. The XPath
    root node has all top-level configuration data nodes in all
    modules as children.

    o If the context node represents state data, the tree is all state
    data on the device, and the datastore. The XPath root
    node has all top-level data nodes in all modules as children.

    o If the context node represents notification content, the tree is
    the notification XML instance document. The XPath root node has
    the element representing the notification being defined as the
    only child.

    o If the context node represents RPC input parameters, the tree is
    the RPC XML instance document. The XPath root node has the
    element representing the RPC operation being defined as the only
    child.

    o If the context node represents RPC output parameters, the tree is
    the RPC reply instance document. The XPath root node has the
    elements representing the RPC output parameters as children.

    The result of the XPath expression is converted to a boolean value
    using the standard XPath rules.

    Note that the XPath expression is conceptually evaluated. This means
    that an implementation does not have to use an XPath evaluator on the
    device. The “when” statement can very well be implemented with
    specially written code.

    8 constraints

    第八章仅仅给出目录,具体内容感觉暂时不需要看。

    8.1 constraints on data

    8.2. Hierarchy of Constraints

    8.3. Constraint Enforcement Model

    8.3.1. Payload Parsing

    8.3.2. NETCONF Processing

    8.3.3. Validation

    9 内置类型

    这一章暂时没有必要看。稍微对编程语言有点了解,就能把这里的内置类型理解个差不多。遇到问题的时候再回头翻原文吧。

    10 更新module

    这一章内容比较少,不过又不是自己写module,所以暂时也没必要看。

    11 YIN

    好像完全没有见过YIN的应用。

    一个YANG module能被转换为一种可选的基于XML语法的格式,称为YIN。被转换的module称为YIN module。本小节描述了这YANG和YIN这两种格式之间的映射关系。

    YANG和YIN格式使用不同的符号包含了同样的信息。YIN的符号使得开发者能够在XML中表示YANG的data models,因此能够使用基于XML的工具对数据做过滤,验证,代码和文档的自动生成以及其它的工作。想XSLT或XML 验证器这样的工具就能用到了。

    YANG和YIN之间的映射不会改变model本身的内容。comments和whitespace不会被保留。

    11.1 正规的YIN定义

    在YANG的keywords和YIN的elements之间有一对一的双射。一个YIN element的local name等同于对应的yANG的keyword。这意味着,YIN文档中的文档元素(root)总是和YANG中的或对应。

    对应到YANG keywords的YIN elements的namespace是“urn:ietf:params:xml:ns:yang:yin:1”。

    对应到YANG的extension keywords的YIN elements属于extension关键词通过“extension”声明宣告的YANG module的namespace。

    所有的YIN elements的名字 MUST 上述指定的namespaces相匹配,也就是要使用标准的[XML-NAMES]机制,比如:“xmlns”以及“xmlns:xxx”属性。

    YANG声明的参数在YIN中是作为XML attribute或者keyword element的subelement而存在。Table 1定义了YANG keywords到YIN的映射关系。对于extensions来说,参数映射是在“extension”声明中指定的(见Section 7.17)。对于参数,有下面的规则:

    • 如果参数被映射为一个attribute,则该attribute没有namespace。
    • 如果参数被映射为一个element,则其namespace和其parent keyword element一样。
    • 如果参数被映射为一个element,则它 MUST 是keyword element的第一个子节点。

    YANG声明的substatements会被映射为该声明对应的keyword element的children,substatements之间的相对顺序 MUST 和YANG中定义的顺序完全一致。

    YANG中的comments MAY 映射为XML的comments。

               Mapping of arguments of the YANG statements.
    
            +------------------+---------------+-------------+
            | keyword          | argument name | yin-element |
            +------------------+---------------+-------------+
            | anyxml           | name          | false       |
            | argument         | name          | false       |
            | augment          | target-node   | false       |
            | base             | name          | false       |
            | belongs-to       | module        | false       |
            | bit              | name          | false       |
            | case             | name          | false       |
            | choice           | name          | false       |
            | config           | value         | false       |
            | contact          | text          | true        |
            | container        | name          | false       |
            | default          | value         | false       |
            | description      | text          | true        |
            | deviate          | value         | false       |
            | deviation        | target-node   | false       |
            | enum             | name          | false       |
            | error-app-tag    | value         | false       |
            | error-message    | value         | true        |
            | extension        | name          | false       |
            | feature          | name          | false       |
            | fraction-digits  | value         | false       |
            | grouping         | name          | false       |
            | identity         | name          | false       |
            | if-feature       | name          | false       |
            | import           | module        | false       |
            | include          | module        | false       |
            | input            | <no argument> | n/a         |
            | key              | value         | false       |
            | leaf             | name          | false       |
            | leaf-list        | name          | false       |
            | length           | value         | false       |
            | list             | name          | false       |
            | mandatory        | value         | false       |
            | max-elements     | value         | false       |
            | min-elements     | value         | false       |
            | module           | name          | false       |
            | must             | condition     | false       |
            | namespace        | uri           | false       |
            | notification     | name          | false       |
            | ordered-by       | value         | false       |
            | organization     | text          | true        |
            | output           | <no argument> | n/a         |
            | path             | value         | false       |
            | pattern          | value         | false       |
            | position         | value         | false       |
            | prefix           | value         | false       |
            | presence         | value         | false       |
            | range            | value         | false       |
            | reference        | text          | true        |
            | refine           | target-node   | false       |
            | require-instance | value         | false       |
            | revision         | date          | false       |
            | revision-date    | date          | false       |
            | rpc              | name          | false       |
            | status           | value         | false       |
            | submodule        | name          | false       |
            | type             | name          | false       |
            | typedef          | name          | false       |
            | unique           | tag           | false       |
            | units            | name          | false       |
            | uses             | name          | false       |
            | value            | value         | false       |
            | when             | condition     | false       |
            | yang-version     | value         | false       |
            | yin-element      | value         | false       |
            +------------------+---------------+-------------+
    
                                  Table 1
    

    11.1.1 使用用例

    下面的YANG module:

     module acme-foo {
         namespace "http://acme.example.com/foo";
         prefix "acfoo";
    
         import my-extensions {
             prefix "myext";
         }
    
         list interface {
             key "name";
             leaf name {
                 type string;
             }
    
             leaf mtu {
                 type uint32;
                 description "The MTU of the interface.";
                 myext:c-define "MY_MTU";
             }
         }
     }
    

    其中的“c-define”定义在Section 7.7.3,将上述module转化为下面的YIN:

         <module name="acme-foo"
                 xmlns="urn:ietf:params:xml:ns:yang:yin:1"
                 xmlns:acfoo="http://acme.example.com/foo"
                 xmlns:myext="http://example.com/my-extensions">
    
           <namespace uri="http://acme.example.com/foo"/>
           <prefix value="acfoo"/>
    
           <import module="my-extensions">
             <prefix value="myext"/>
           </import>
    
           <list name="interface">
             <key value="name"/>
             <leaf name="name">
               <type name="string"/>
             </leaf>
             <leaf name="mtu">
               <type name="uint32"/>
               <description>
                 <text>The MTU of the interface.</text>
               </description>
               <myext:c-define name="MY_MTU"/>
             </leaf>
           </list>
         </module>

    12 YANG ABNF Grammar

    ABNF, Augmented Backus-Naur Form

    这一章看不懂,后面就不粘了。

    在YANG中,几乎所有的statements都是无序的。ABNF grammar 【RFC5234】 为这些声明定义了标准的顺序。为了提高module的可读性, RECOMMENDED 有序。

    13 YANG相关错误的Error Responses

    这一章对于我们实现来说,并不关心,所以跳过。

    14 IANA Considerations

    这一章同样没什么用。

    This document defines a registry for YANG module and submodule names.
    The name of the registry is “YANG Module Names”.

    The registry shall record for each entry:

    o the name of the module or submodule

    o for modules, the assigned XML namespace

    o for modules, the prefix of the module

    o for submodules, the name of the module it belongs to

    o a reference to the (sub)module’s documentation (e.g., the RFC
    number)

    There are no initial assignments.

    For allocation, RFC publication is required as per RFC 5226
    [RFC5226]. All registered YANG module names MUST comply with the
    rules for identifiers stated in Section 6.2, and MUST have a module
    name prefix.

    The module name prefix ‘ietf-’ is reserved for IETF stream documents
    [RFC4844], while the module name prefix ‘irtf-’ is reserved for IRTF
    stream documents. Modules published in other RFC streams MUST have a
    similar suitable prefix.

    All module and submodule names in the registry MUST be unique.

    All XML namespaces in the registry MUST be unique.

    This document registers two URIs for the YANG and YIN XML namespaces
    in the IETF XML registry [RFC3688]. Following the format in RFC
    3688, the following have been registered.

     URI: urn:ietf:params:xml:ns:yang:yin:1
    
     URI: urn:ietf:params:xml:ns:yang:1
    
     Registrant Contact: The IESG.
    
     XML: N/A, the requested URIs are XML namespaces.
    

    This document registers two new media types as defined in the
    following sections.

    14.1 Media type application/yang

    MIME media type name: application

    MIME subtype name: yang

    Mandatory parameters: none

    Optional parameters: none

    Encoding considerations: 8-bit

    Security considerations: See Section 15 in RFC 6020

    Interoperability considerations: None

    Published specification: RFC 6020

    Applications that use this media type:

    YANG module validators, web servers used for downloading YANG
    modules, email clients, etc.
    

    Additional information:

     Magic Number:  None
    
     File Extension:  .yang
    
     Macintosh file type code:  'TEXT'
    

    Personal and email address for further information:
    Martin Bjorklund mbj@tail-f.com

    Intended usage: COMMON

    Author:
    This specification is a work item of the IETF NETMOD working group,
    with mailing list address netmod@ietf.org.
    Change controller:
    The IESG iesg@ietf.org

    14.2 Media type application/yin+xml

    MIME media type name: application

    MIME subtype name: yin+xml

    Mandatory parameters: none

    Optional parameters:

     "charset":  This parameter has identical semantics to the charset
     parameter of the "application/xml" media type as specified in
     [RFC3023].
    

    Encoding considerations:

     Identical to those of "application/xml" as
     described in [RFC3023], Section 3.2.
    

    Security considerations: See Section 15 in RFC 6020

    Interoperability considerations: None

    Published specification: RFC 6020

    Applications that use this media type:

    YANG module validators, web servers used for downloading YANG
    modules, email clients, etc.
    

    Additional information:

     Magic Number:  As specified for "application/xml" in [RFC3023],
                    Section 3.2.
    
     File Extension:  .yin
    
     Macintosh file type code:  'TEXT'
    

    Personal and email address for further information:
    Martin Bjorklund mbj@tail-f.com

    Intended usage: COMMON

    Author:
    This specification is a work item of the IETF NETMOD working group,
    with mailing list address netmod@ietf.org.

    Change controller:
    The IESG iesg@ietf.org

    15 Security Considerations

    This document defines a language with which to write and read
    descriptions of management information. The language itself has no
    security impact on the Internet.

    The same considerations are relevant as for the base NETCONF protocol
    (see [RFC4741], Section 9).

    Data modeled in YANG might contain sensitive information. RPCs or
    notifications defined in YANG might transfer sensitive information.

    Security issues are related to the usage of data modeled in YANG.
    Such issues shall be dealt with in documents describing the data
    models and documents about the interfaces used to manipulate the data
    e.g., the NETCONF documents.

    Data modeled in YANG is dependent upon:

    o the security of the transmission infrastructure used to send
    sensitive information.

    o the security of applications that store or release such sensitive
    information.

    o adequate authentication and access control mechanisms to restrict
    the usage of sensitive data.

    YANG parsers need to be robust with respect to malformed documents.
    Reading malformed documents from unknown or untrusted sources could
    result in an attacker gaining privileges of the user running the YANG
    parser. In an extreme situation, the entire machine could be
    compromised.

    16 贡献者

    The following people all contributed significantly to the initial
    YANG document:

    - Andy Bierman (Brocade)
    - Balazs Lengyel (Ericsson)
    - David Partain (Ericsson)
    - Juergen Schoenwaelder (Jacobs University Bremen)
    - Phil Shafer (Juniper Networks)
    

    17 Acknowledgements

    The editor wishes to thank the following individuals, who all
    provided helpful comments on various versions of this document:
    Mehmet Ersue, Washam Fan, Joel Halpern, Leif Johansson, Ladislav
    Lhotka, Gerhard Muenz, Tom Petch, Randy Presuhn, David Reid, and Bert
    Wijnen.

    18 引用

    18.1 对标准的引用

    [ISO.10646]  International Organization for Standardization,
                "Information Technology - Universal Multiple-Octet Coded
                Character Set (UCS)", ISO Standard 10646:2003, 2003.
    
    [RFC2119]    Bradner, S., "Key words for use in RFCs to Indicate
                Requirement Levels", BCP 14, RFC 2119, March 1997.
    
    [RFC3023]    Murata, M., St. Laurent, S., and D. Kohn, "XML Media
                Types", RFC 3023, January 2001.
    
    [RFC3629]    Yergeau, F., "UTF-8, a transformation format of ISO
                10646", STD 63, RFC 3629, November 2003.
    
    [RFC3688]    Mealling, M., "The IETF XML Registry", BCP 81, RFC 3688,
                January 2004.
    
    [RFC3986]    Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
                Resource Identifier (URI): Generic Syntax", STD 66,
                RFC 3986, January 2005.
    
    [RFC4648]    Josefsson, S., "The Base16, Base32, and Base64 Data
                Encodings", RFC 4648, October 2006.
    
    [RFC4741]    Enns, R., "NETCONF Configuration Protocol", RFC 4741,
                December 2006.
    
    [RFC5226]    Narten, T. and H. Alvestrand, "Guidelines for Writing an
                IANA Considerations Section in RFCs", BCP 26, RFC 5226,
                May 2008.
    
    [RFC5234]    Crocker, D. and P. Overell, "Augmented BNF for Syntax
                Specifications: ABNF", STD 68, RFC 5234, January 2008.
    
    [RFC5277]    Chisholm, S. and H. Trevino, "NETCONF Event
                Notifications", RFC 5277, July 2008.
    
    [XML-NAMES]  Hollander, D., Tobin, R., Thompson, H., Bray, T., and A.
                Layman, "Namespaces in XML 1.0 (Third Edition)", World
                Wide Web Consortium Recommendation REC-xml-names-
                20091208, December 2009,
                <http://www.w3.org/TR/2009/REC-xml-names-20091208>.
    
    [XPATH]      Clark, J. and S. DeRose, "XML Path Language (XPath)
                Version 1.0", World Wide Web Consortium
                Recommendation REC-xpath-19991116, November 1999,
                <http://www.w3.org/TR/1999/REC-xpath-19991116>.
    
    [XSD-TYPES]  Malhotra, A. and P. Biron, "XML Schema Part 2: Datatypes
                Second Edition", World Wide Web Consortium
                Recommendation REC-xmlschema-2-20041028, October 2004,
                <http://www.w3.org/TR/2004/REC-xmlschema-2-20041028>.                           
    

    18.2 对informative文稿的引用

    [RFC2578]    McCloghrie, K., Ed., Perkins, D., Ed., and J.
                Schoenwaelder, Ed., "Structure of Management Information
                Version 2 (SMIv2)", STD 58, RFC 2578, April 1999.
    
    [RFC2579]    McCloghrie, K., Ed., Perkins, D., Ed., and J.
                Schoenwaelder, Ed., "Textual Conventions for SMIv2",
                STD 58, RFC 2579, April 1999.
    
    [RFC3780]    Strauss, F. and J. Schoenwaelder, "SMIng - Next
                Generation Structure of Management Information",
                RFC 3780, May 2004.
    
    [RFC4844]    Daigle, L. and Internet Architecture Board, "The RFC
                Series and RFC Editor", RFC 4844, July 2007.
    
    [XPATH2.0]   Berglund, A., Boag, S., Chamberlin, D., Fernandez, M.,
                Kay, M., Robie, J., and J. Simeon, "XML Path Language
                (XPath) 2.0", World Wide Web Consortium
                Recommendation REC-xpath20-20070123, January 2007,
                <http://www.w3.org/TR/2007/REC-xpath20-20070123>.                
    [XSLT]       Clark, J., "XSL Transformations (XSLT) Version 1.0",
                World Wide Web Consortium Recommendation REC-xslt-
                19991116, November 1999,
                <http://www.w3.org/TR/1999/REC-xslt-19991116>.
    

    作者联系地址

    Martin Bjorklund (editor)
    Tail-f Systems

    EMail: mbj@tail-f.com

    展开全文
  • 企业大中台策略剖析

    千次阅读 多人点赞 2018-10-24 12:02:45
    随着数字化和互联网时代的来临,云计算、大数据、微服务、物联网、移动互联等各种新兴技术为IT产业带来无限机遇的同时,也为企业业务不断发展带来支撑,伴随着企业规模不断扩大、业务多元化、创新化的发展,“大中台...

            随着数字化和互联网时代的来临,云计算、大数据、微服务、物联网、移动互联等各种新兴技术为IT产业带来无限机遇的同时,也为企业业务不断发展带来支撑,伴随着企业规模不断扩大、业务多元化、创新化的发展,“大中台、小前台”的技术架构模式出现,由于公司的发展要求,笔者经常接触大中台这一理念,结合公司主打SOA集成平台、数据治理等产品和方案,在学习过程中有自己一些的理解,本文主要与大家分享笔者的认知,希望能够对有需要的朋友们提供参考和帮助。

    1. 定义阐述

           中台概念出现之前,在信息化模式上,前端为支撑业务的应用端,后端为各个应用系统,为前端用户,如:客户、供应商、伙伴、社会提供服务,但随着市场、用户需求、业务的多变性,底层僵硬的应用无法及时提供支撑。企业需要一个强大的中间层为高频多变的业务提供支撑,为不同的受众用户提供多端访问渠道,基于此类需求“中台”概念出现,不过凑巧是阿里提出,接着开始对企业客户、中间件厂商、数据平台厂商、甚至传统应用软件厂商都有较大的概念冲击。恰逢此时,微服务技术和架构、容器化的生态、Devops概念和工具处于大发展的阶段,然后基于“大中台、小前台”的信息化建设模式开始流行。

    1.1 概念产生

            对于大中台来讲,现在并没有十分严格的定义,每个企业对其的理解都是不同的,有的在技术上使用大中台模式,有的在业务上使用大中台模式,有的将两者相结合。“大中台,小前台”的机制最初阿里提出的时候,主要应用于O2O线上线下协同、电商等场景,对于电商来说,市场环境是瞬息万变的,而前台是主要的一线业务,这时就需要一个强大的技术中台提供快速设计方法和系统性后端服务,去应对市场变化,灵活快速的做出应对策略。

    1.2 应用模式

            就阿里平台与个体商家的关系而言,虽然互相为独立的主体,但因为业务之间存在的联系,一定程度上已经分不清彼此,对于阿里来说,“大中台,小前台”理念中的前台强调创新和灵活多变,包括云计算、大数据、零售电商、广告业务、物流配送、售后维护以及其它业务;中台强调协调和规划管控,为前台业务开展提供底层技术、数据等资源支撑,多为平台类体系产品,一般都是外购、开源、自研相结合、不同的企业比重不同。

    2. 中台划分

            如今大中台模式不再拘泥于电商行业,随着发展和演变逐渐走向集团型、大型企业,为整个集团提供运营数据能力、技术能力、支撑能力、产品能力等,这时对于大中台的运用与划分也不再只是技术中台,还包括基础中台、数据中台、业务中台共同构成。

    2.1 基础中台

            基础中台为大中台模式的底层基础支撑,也称之为PaaS容器层,而对于中台模式来说,要求平台灵活高效,这就意味着对容器集群管理与容器云平台的选择十分重要,技术运用的是否到位直接影响平台的开发效率和运维程度,在这方面目前Docker和K8S独占鳌头,同时对应的DevOPS与CI/CD理念也随着兴起。

            敏捷开发和DevOps都是为了更好更快的发布产品而提出的一种理念,而CI/CD是实现这两者理念的一种方法,即持续集成、持续交付。这些理念、工具、方法论作为基础中台组成部分来支撑中台模式。

    2.2 技术中台

            中台技术不是空穴来风,是随着平台化架构的发展所演进的产物,从技术层面来讲,大中台技术延续平台化架构的高聚合、松耦合、数据高可用、资源易集成等特性,之后结合微服务方式,将企业核心业务下沉至基础设施中,基于前后端分离的模式,为企业打造一个连接一切、集成一切的共享平台,技术中台架构如下:

            从技术中台架构中可以看出,底层为应用提供层,即企业信息化系统或伙伴客户相关信息化系统等;上层为集成PaaS层,将服务总线、数据总线、身份管理、门户平台等中间件产品和技术融入,做为技术支撑;DaaS数据层通过数据中台,结合主数据、大数据等技术,发挥数据治理、数据计算、配置分析的能力,服务中台层与共享服务层共同支持应用层中的行业业务,为用户提供个性化的服务。

    2.3 数据中台

            随着数字化时代到来,互联网、云计算、大数据、人工智能等技术推动着传统企业的数字化转型,未来企业对人、事、物的管理必定会被数字化全面替代,在数据中台部分,帮助企业进行数据管理,打造数字化运营能力。数据中台中不仅包括对业务数据的治理,还包括对海量数据的采集、存储、计算、配置、展现等一系列手段,数据中台架构如下:

            从下至上可以看出,主要从系统、社交、网络等渠道采集结构化或半结构、非结构化数据,按照所需的业态选择不同技术手段接入数据,之后将数据存入到相应的数据库中进行处理,通过主数据治理清理脏数据,保证所需数据的一致性、准确性、完整性,之后将数据抽取或分发至计算平台中,通过不同的分析手段根据业务板块、主题进行多维度分析、加工处理,之后得到有价值的数据用于展现,辅助决策分析。

    2.4 业务中台

            技术中台从技术角度出发,数据中台从业务数据角度出发,业务中台站在企业全局角度出发,从整体战略、业务支撑、连接用户、业务创新等方面进行统筹规划,由基础中台、技术中台、数据中台联合支撑来建设业务中台,业务中台架构如下:

            底层以PaaS为核心的互联网中台作为支撑,通常将开源的、外采的、内研的信息化系统、平台等作为基础的能力封装成核心技术层,通过系统整合、业务流程再造、数据治理分析等一系列活动为企业的业务提供支撑,形成特有的业务层,连接上下游伙伴、内外部客户、设备资源系统、建立平衡的生态环境,支撑业务的发展与创新。

    3. 前置条件

            随着“大中台,小前台”模式的演进,很多企业开始纷纷效仿大中台这一业务模式,但并不是所有企业都可以成功实行中台策略,事实上大中台的构建如同大数据平台的建设一样,要具备特定的前置条件,下面主要从行业特性、企业体量、技术实力等几个方面进行分析。

    3.1 行业特性

            大中台策略的产生是基于互联网背景之下,虽由电商行业兴起,但用户群体面向ToBs,用于打造产业生态链、衔接上游供应商、下游代理商/经销商业务,帮助企业前台贴近用户,提供更好、更人性化服务,提升用户体验、加快业务交互频率,中台和后台提供管控协调和技术支撑。在当前阶段,“大中台、小前台”这一模式在金融、银行、政府、能源等行业领域已经开始展开建设了。

    3.2 企业体量

            大中台模式建设对企业体量有较高的要求,通常为龙头企业、行业楚翘,组织结构庞大而复杂,存在众多有实力的子公司或下级单位,并且整体业务上多元化:多板块、多业态。集团内部拥有较为充足的资金力量、能力较强的技术团队,良好的信息化基础设施建设,具备强大的能力去整合业务和上下游的业务和信息化系统。

    3.3 技术实力

            对于构建大中台业务模式的企业来说,内部需要具备一定的技术实力,首先要对自身业务领域及业务流程模式具备较深的了解,之后对中台需要的技术/产品(开源的/非开源的)具备扎实的基础,以便后续对中台成果维护的同时发现问题并进行改进,如果当前企业暂时不具备独立构建或维护中台成果的能力,那么可以与一些技术实力强的厂商共同合作完成,在构建的过程中能够迅速地学习对方的能力。

    4. 构建模式

            在满足上述前置条件之后,企业对于大中台的构建通常分为三种模式,一种为全部外采,外包给实施团队;一种为吸收开源融合业务,之后将成果开源;一种为自研、开源相结合,下面将具体阐述每种模式。

    4.1 外部采购

            排除信息化团队的能力不谈,使用该种模式的企业通常拥有雄厚的资金,或是在行业特性、业务方面与外采的大中台产品或技术框架有一定的相似度,业务内容具备较高的复用性,否则在独有业务定制开发方面会花费更高的人力、时间、金钱成本,得不偿失。对于外采模式,通常不会购入成品中台,而是购入开放的中间件平台类产品,如ESB、Portal、IDM、MDM、BI等作为技术中台、数据中台提供能力支撑。

    4.2 基于开源

            该种模式企业通常拥有自己的信息化团队,当然不排除一些企业注重时间成本而直接高薪聘请专业信息化团队打造大中台架构,对于底层技术,不需要花费过多时间去自研,使用开源框架及产品作为支撑即可,对于专有业务结合扩展开发,打造属于自身业务发展的大中台架构。部分企业基于这种模式,会将研究成果全部或部分开源出去,供其他类似行业使用借鉴。

    4.3 自主研发

            使用该种模式的企业同样具备信息化团队,在大中台技术架构上,不想全部采用外部吸收的技术,也不愿将平台后续的扩展与维护受限于他人,在特有业务或主营业务方面的技术产品选择自研,底层通用框架方面选择当前开源的技术与产品,部分技术中台、数据中台中涉及产品选择外采,并基于在外部技术团队实施的过程中,吸收、学习产品使用的能力,后期维护扩展。

    4.4 最佳实践

            无论是微服务还是大中台理念,都是基于中国市场特有业务,根据传统架构模式演变而来,无论是构建成果还是发挥的作用都更加适应中国模式的发展,当前对大中台的构建也应该遵循中国市场独有的最佳实践。

            大中台模式不仅对企业内部进行整体管控,还是商业模式的支撑手段及营销渠道,构建时应当注重对中台建设整体的管控能力,在具备充足人力、财力的情况下,也不必采用全部自建的模式,对于通用类软件在满足开发性前提下考虑外采,由原厂商提供技术支持,对主营业务建设则以自建为主,结合外采一些技术平台类产品、整体解决方案来实现,着重衡量产品的开放性、敏捷性、扩展性、维护性,实施团队的成熟度、专业性、知识传递性等,企业在建设过程中完成技能培训、知识转移,沉淀最佳实践,后续独立进行平台搭建、扩展、改造、维护,最终实现中台建设自主可控。

    5. 延展分析

            随着“大中台,小前台”模式的出现,很多人会与前段时间炒得很火的微服务与PaaS平台、SOA相比较,今天笔者在这里将当今较火的几个词语,PaaS平台、微服务、SOA与大中台之间的关系做对比分析。

    5.1 中台与微服务

            笔者之前的文章中曾提到过,微服务架构是云时代下应用系统的技术架构、建设方式,基于微服务将复杂臃肿的单体应用进行细粒度的服务拆分,经过组件分离各自拥有独立的生命周期,并按需进行扩展,微服务的实现有效打破了组件之间的技术依赖,使每个服务各自选择最合适的技术进行实现,微服务模式下控制层访问到服务层,典型方式是单体应用基于“前后端分离”模式来开发。

            而大中台服务架构是微服务架构的升级,策略为“大中台、小前台”,打造共享服务平台的模式,中台的最终效果为前台单体应用构建灵活的业务服务开发、治理体系,基于集成平台产品套件,融合集成后台各应用系统、支撑业务创新变化。这种思路实现基础和共性能力的下沉和剥离,相对于整体来说,各个基于大中台中的单体应用从数据库到服务层再到前端展现都需要纵向独立的拆分松耦合的微服务模块。微服务架构“大中台、小前台”模式的特性,同时要求技术中台、数据中台都有强大微服务提供能力。

    5.2 中台与PaaS平台

            云计算通常来说包括IaaS、PaaS、SaaS三个层面,在中国IaaS发展相对来说较为成熟,阿里云、腾讯云、华为云其实更多都是IaaS层面的产品;SaaS发展在前几年(2010-2016)都是看起来很风光的、尤其是看到SaaS模式的Saleforce以460亿美金高价位被Oracle收购后,中国的SaaS 厂商都像打鸡血似的,踌躇满志以为会成为中国的Salefore,然而喧嚣过后一地鸡毛,在更多的炮灰倒下之后,残留更多是挣扎在生死线上。

            PaaS作为云计算的服务模式之一,是位于IaaS和SaaS模型之间的一种云服务,早些年在中国发展一直很迟缓,究其原因一方面是相关技术不够成熟、另外一方面没有合适的业务模式、盈利方式。现在基于Docker、K8S为代表的容器技术和生态,微服务的理念和相关工具、DevOps的相关产品和方法体系逐渐成熟起来,再加上“大中台,小前台”的概念抛出,实际的需求呼唤,PaaS开始在中国这片古老的大地野蛮生长。

            “大中台、小前台”其实也是PaaS平台技术具体落地的一种实现方式。PaaS平台引入Docker技术后,采用虚拟机技术实现了对应用程序、系统以及资源之间的有效隔离,保证了资源的独立性,不被其他人占用。而大中台的建设与PaaS的容器层CaaS、K8S、Docker等技术相结合,将具有PaaS能力应用服务器、数据库、应用支撑平台,如Portal、MDM、ESB等以私有镜像模式封装在Docker容器中,供K8S来调度、编排、治理,最终形成一个可以具有集成性、开发扩展性、支撑快速创新的中台模式。

    5.3 中台与SOA架构

            SOA(Service OrientedArchitecture )面向服务架构,它是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。对于SOA架构来说不同的人有不同的定义,它曾被称之为一种架构体系、一种方法论、治理理念等,大中台模式与SOA架构在理念上是一脉相承的,SOA相关产品套件可以作为技术中台与数据中台支撑大中台策略,大中台策略从技术角度来看,也可以作为SOA中开发集成模式的一种演化变形。

            技术中台中的相关产品,如:服务总线、数据总线、身份管理、门户管理等技术的实现,都是SOA综合集成方案的拆分与变形,数据中台中的数据治理、分析能力同为SOA集成方案的重要组成部分。同时在开发集成方案中,采用SOA整合套件作为基础技术框架及应用支撑平台,梳理、制定出面向行业业务的标准接口和管理体系,根据标准接口规范集成行业的典型应用系统,对于个性化业务进行快速定制开发,之后通过前端平台展现。

            随着“大中台、小前台”技术架构、业务模式的兴起,的确为企业带来新的治理思路及支撑业务创新的方案,企业根据自身业务发展构建大中台从方向来说无疑是正确的,但要遵循前置条件及适合企业的最佳实践,根据自身当前的业务模式、技术平台来合理选择底层框架、引入开源和商用产品,结合内部研发来打造符合企业特色“大中台、小前台”技术架构体系,满足众多受众(内部用户、高管、供应商、分销商、客户、银行以及政府监管部门等)的高频变化,满足业务发展、支撑产业链建设升级,不断强化企业在行业内、生态链中的江湖地位。

    展开全文
  •  员工真能把企业当成家,正如文中员工所讲:“不管你如何为公司卖命,当公司需要你的时候,你曾经做的一切都不再有意义。”  员工真能把企业当成家,正如文中柳传志所讲:“一个企业应该遵循的最根本原则...
  • 因为企业后台往往并能很好的支撑前台快速创新响应用户的需求,后台更多解决的是企业管理效率问题,而台要解决的才是前台的创新问题 大多数企业已有的后台,要么前台根本就用了,要么好用,要么变更速度...
  • 2019独角兽企业重金招聘Python工程师标准>>> ...
  • 明*与暗箭,显然都是让企业陷入竞争漩涡,但好在企业多少还能预见与控制,冷箭则不同。冷箭几乎没有征兆,当企业发现冷箭的时候,大部分是已非正常致死的时候。 2004年前,中国的豆油压榨企业有1000多家,这些豆油...
  • 2019独角兽企业重金招聘Python工程师标准>>> ...
  • CSS标签选择器

    千次阅读 2017-07-04 00:00:27
    1. 标签选择器选定的是当前界面所有该名称的标签,而能单独选定某一标签; 2. 标签选择器无论标签藏得多深都能找到; 3. 只要是HTML的标签都可以作为标签选择器。 2.id选择器 作用:根据指定的id名称找到...
  • 坊间对各大公司内部的职级、文化、体系等关注度一直很高,但各方因保密协议的约束,网上这类的知识却少之又少,大多也只停留在听说这个阶段。什么阿里的p7,腾讯5啊,字节3-1啊,简直能把人绕晕。对等的消息,如果...
  • SAP和开放标准

    千次阅读 2006-11-06 09:40:00
    最近SAP宣布其NetWeaver平台通过了Java EE 5兼容...开放标准在SAP产品中一直扮演着重要的角色,特别是进入企业级SOA时代后,SAP不遗余力地执行和制定开放标准来降低企业级SOA的拥有成本。譬如:SAP NetWeaver作为第一个
  • 企业为什么要建台?从数据台到AI台。 白发川 CMKT咨询圈 前天 https://mp.weixin.qq.com/s/cwtaHltF53yzV7zjZAah8g?from=groupmessage&amp;isappinstalled=0 作者:王健 来源:健荐(微信号: gh_3b7794be...
  • 作者 | 赵陈婷 ...这家1998年成立的企业,在过去的20年来一直有着太过鲜明的刘强东个人标签。 最直接的原因是虽然经过多次融资稀释股权,腾讯如今是京东的大股东,但是牢牢攥着京东近8成投票权的刘强东...
  • 敢冒险就不是硅谷的企业

    万次阅读 热门讨论 2006-08-30 15:19:00
    idapted是一个月前刚刚进入中国的一家互联网创新企业,几个主要合伙人都是斯坦福的毕业生,主要的业务方向是通过新一代的Web技术向用户提供语言培训服务,其业务模型清晰,核心团队非常强大。Jonathan是这家公司的...
  • 揭秘: 优秀CIO的OA选型标准

    千次阅读 2018-04-20 16:33:23
    OA选型一直企业信息化建设面临的难题,企业内部没有人懂OA系统,OA行业也没有什么权威机构和数据可以参考,OA系统厂商排名纯属自嗨,那么,到底该如何进行OA选型?看成功企业的选型标准!这些企业CIO在选型时积累...
  • H.264再学习 -- H.264视频压缩标准

    万次阅读 2017-10-13 09:04:35
    H.264 这部分一直在讲,但是却没有系统的来说。接下来要详细。 参看:H.264视频压缩标准 一、简介 H.264是最新的视频压缩标准,它也称为MPEG-4 Part 10或AVC(高级视频编码)。据预测,在未来几年内H.264将成为...
  • 蓝牙信技术的发展蒸蒸日上,该技术能为消费者、商家和工业环境实现“接近感知应用”例如:  · 终端消费者可以基于他们所处的位置获得即时优惠券和定制产品;  · 商家可以从针对消费者购买习惯的可视度提升...
  • SAP不是企业信息化的救世主

    千次阅读 热门讨论 2007-04-28 23:15:00
    的文章,大意是探讨SAP套件比自行开发更适用于企业信息化建设,列了一些理由,如SAP的行业经验、 系统构架的稳定、可扩展性、业务适应性及兼容性等。虽然我不是SAP的专家,但毕竟和SAP的产品和顾问打交道了好多年,...
  • 因此,在Zachman的EA框架基础上,需要对企业架构框架进行重构,主要叠加人、物、事的行为,进而提出智慧企业架构框架SEAF,并就智慧企业架构框架进行概括性阐述,涉及实现SEAF的方法论,供企业架构专家讨论,...
  • 转载自:http ://www.eepw.com.cn/article/201703/344714.htm 蓝牙信技术的发展蒸蒸日上,该技术能为消费者,商家和工业环境实现“接近... ·工业企业可以从改善的资产监控能力和资产利用率增加收益。 可能...
  • 微信企业号开发:微信考勤

    千次阅读 2015-08-25 09:22:38
    使用微信考勤,有很多企业号应用都有,但如何实现呢...当然了这些也只是表明曾经在某一个位置,并表明一直都在,就好像打了卡,并代表一直都在公司上班,也可能打卡后,就逛街去了。 2在获得了用户的位置信息后,
  • 先选择服务器如何选择SQL Server 2012 选择自己要的版本,这里笔者选的是中文企业版,下载地址附上,复制到迅雷下载即可 注意这里的是64位版,如果32位机器去网站上找x86的版本,笔者还是建议换成64位的系统吧 ed...
  • 从昨天开始就听到这个消息,但一直没有确切的消息来源。今天早上终于从工信部的网站上查到了这个通知。集团入围2015年两化融合管理体系贯标试点企业,本次一共有600家企业入围,其中黑龙江有4家。入围贯标企业对于...
  • WIFI Direct 标准 连接

    万次阅读 2012-08-01 18:45:00
    Wi-Fi Direct与Wi-Fi并是一回事儿。符合Wi-Fi Direct标准的设备在无须热点基站、路由或AP的情况下,就可以方便地与其他设备实现直接连接、传输数据或共享应用。而我们目前大量应用的Wi-Fi电脑、手机等,都能主动...
  • 某大型企业围绕供应链建立了多个IT系统,各系统之间又需要数据交换和协同业务处理,这就要求各系统进行集成,目前,该企业的系统集成现状是:数据与处理逻辑分离,数据以文件方式独立传送,处理逻辑依赖某轻量的跨...
  • 企业经营管理成熟度

    千次阅读 2014-03-16 17:07:45
    企业经营管理成熟度我自己把企业管理成熟度分为六个层级:1、组织...但我看到机场大师多年绝、刘一秒万人体育场培训、微信营销万元课程趋之若鹜,我发现我还是把中国大量企业看高了。大量企业寻租关系而起步、逐水
  • from=timeline 数据台最早是阿里提出的,但真正火起来是 2018 年,我们能感受到行业文章谈论数据台的越来越多。...尽管数据台的文章很多,但是一千人眼里有一千个数据台,到底什么是数据台?数据台包...
  • 2019-06-10 16:10:12 莫颜 时代壹周刊 ...我无所谓,推着单车慢慢地走过去,但透过小车的反光玻璃,我看清他的表情。后来他就搬往别墅去了。” 1996年,已经被联想解除了所有职务的倪...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 189,602
精华内容 75,840
关键字:

企业一直中不了标