OpenDaylight架构简介


在我们跳入代码之前,需要对OpenDaylight控制器进行高级概述。 OpenDaylight是一个模块化平台,大多数模块reusing 一些常见的服务和接口。 每个模块都是在多供应商子项目下开发的。 你可以在这里找到项目的列表。


在OpenDaylight平台上构建应用程序的想法是利用其他平台包中的功能,每个平台包都通过Java接口导出重要的服务。 许多这些服务是在称为MD-SAL的适应层上在提供者 - 消费者模型中构建的。
在OpenDaylight的核心编程中的MD-SAL数据存储涉及采用用于SDN应用开发的模型 - 视图 - 控制方法:
1.YANG Model for 数据,RPC和通知
YANG Model for data, RPC and notifications
2.REST API视图通过RESTconf实现自动生成和访问

3.Java编码处理数据更改,通知和RPC回调
Java Implementation coded to handle data changes, notifications and RPC call backs)



3.1模型驱动的SAL(MD-SAL)

模型驱动的服务适配层(MD-SAL)是平台的内核,不同的层和模块通过API互连。 以下是关于MD-SAL的一些重要注意事项:
   1.每个API都是在构建期间从YANG语言中定义的模型生成的,并且当模型包(model bundle)装入到Karaf平台时加载到控制器中
  2.在平台的核心是逻辑集中的数据存储,其将相关状态保持在两个桶中 - 1)配置数据存储,2)操作数据存储。

  3.使用MD-SAL映射逻辑,所有事件调用和数据通过此中央数据存储区从“提供者”到“消费者”





3.2 YANG 模型

OpenDaylight大量使用YANG来建模在不同模块间的数据,通知或 remote procedure call (RPC)。 对于那些不熟悉YANG的学生,我们建议您通过Tail-F系统学习YANG教程。 简而言之,YANG是一种用于描述存储在容器内的树层次结构中的一些应用程序数据的基本结构的语言。

作为示例,这里是用于存储在opendaylight-inventory.yang中定义的storing nodes (i.e., switches) and node-connectors (i.e., interfaces or ports)的YANG模型的摘录:



module opendaylight-inventory {
    namespace "urn:opendaylight:inventory";
    container nodes {
        list node {
            key "id";
            leaf id {
                type node-id;
            }
            list "node-connector" {
                key "id";
                leaf id {
                    type node-connector-id;
                }
            }
        }
    }
}
一旦在Karaf中加载并且包括在特征文件中(including in the feature file,将该模型提供给MD-SAL平台,MD-SAL为该模块创建两个数据存储:1)配置数据存储,2)操作数据存储。 默认情况下,配置数据存储在控制器的不同运行中保持不变(配置数据存储存储在karaf运行位置中的快照和日志目录中)。



3.3实例标识符 Instance identifiers


应用程序或外部终端用户可以通过MD-SAL事务或RESTconf将数据发布到此数据存储。 单个对象存储在parent-child hierarchy 中,并可通过YANG实例标识符访问。 对于上述YANG模型,假设存在一个存储在数据存储中的node-connector “openflow:1:1″ 。 可以通过创建如下的实例标识符来访问该节点连接器的详细信息:
InstanceIdentifier ncIID = InstanceIdentifier.builder(Nodes.class)
.child(Node.class, new NodeKey(new NodeId("openflow:1")))
.child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId("openflow:1:1")))
.build();


或者,它可以通过RESTconf访问URL:http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/node-connector/openflow:1:1,其中关键字 “opendaylight-inventory”对应于该模块的命名空间,“nodes”对应于树的根级别的容器。

有用的提示:如果您提供了实例标识符,可以通过执行firstKeyOf()或firstIdentifierOf()来提取父对象的实例标识符或键,如下所示:


 InstanceIdentifier nodeIID = ncIID.firstIdentifierOf(Node.class);
        NodeId nodeId = ncIID.firstKeyOf(Node.class, NodeKey.class).getId();



3.4数据存储事务  Data store Transactions


一旦创建实例标识符,就可以使用DataBroker服务对数据存储中的该位置执行读取或写入transactions 。 有两个类(即WriteTransaction和ReadOnlyTransaction)可以帮助你。

假设我们要将一个NodeConnector对象写入数据存储,我们使用以下代码:


WriteTransaction modification = dataBroker.newWriteOnlyTransaction();
        modification.merge(LogicalDataStoreType.CONFIGURATION, ncIID, nodeConnector, true);
        CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
        try {
            commitFuture.checkedGet();
        } catch (Exception e) {
            modification.cancel();
        }

大多数transactions 返回一个Java Future对象。 重要的是检查此Future对象的状态,以查看transactions 是否成功以及是否生成了任何特定输出。


假设我们要从数据存储中读取一个NodeConnector对象,我们使用下面的代码:


 ReadOnlyTransaction readTransaction = dataBroker.newReadOnlyTransaction();
        try {
            Optional optionalData = readTransaction.read(LogicalDataStoreType.CONFIGURATION, ncIID).get();
            if (optionalData.isPresent()) {
                NodeConnector nc = (NodeConnector) optionalData.get();
            }
        } catch (ExecutionException | InterruptedException e) {
            readTransaction.close();
        }


当强制执行集群一致性时,每个transactions 消耗一定量的CPU资源,并且更多。 这可以限制每秒的transactions 数。 在OpenDaylight MD-SAL中,可以执行批处理事务和事务链以获得更好的读取和写入性能。 这些超出了本教程的范围。




3.5高级YANG操作

除了如上所示的基本数据模型,可以在YANG模型中定义以下结构以模拟模块之间的附加服务:
Augmentations(增强):如果没有另外说明,YANG模型可以在新的命名空间中扩展,以在现有数据模型中添加额外的数据。 请注意,Augmentations必须在构建时声明。

例如,对上面显示的Node对象进行OpenFlow规则augmented 以创建流表扩充(flow table augmentation)。 这里是增强树的样子。




Notifications:这些也称为YANG通知。 它用于通过建模数据向注册的侦听器发布一个或多个通知。 在YANG中定义通知会生成Java接口,潜在的侦听器可以“实现”并接收适当的回调。

在我们的示例项目中的tap应用程序中,我们说明了监听节点和节点连接器更新和删除。下面是编写的代码,用于监听opendaylight-inventory.yang中定义的通知。 OpendaylightInventoryListener是一个自动生成的接口,它定义了一个名为onNodeUpdated()的回调函数。


public class TapProvider implements OpendaylightInventoryListener.. {
    public TapAppProvider(..) {
        notificationService.registerNotificationListener(this);
    }
    @Override
    public void onNodeUpdated(NodeUpdated nodeUpdated) {
       //Automatically called when node object is updated        
    }


Remote Procedure Call (RPC):MD-SAL允许一个模块执行与另一个模块的输入/输出的过程调用,而不必担心该过程的实际提供者是谁。 MD-SAL处理适当的路由以映射呼叫者和被叫者。

在我们的示例项目中的tap应用程序中,我们说明执行RPC调用以清除底层交换机上的所有OpenFlow规则。 与通知不同,RPC调用具有唯一的收件人。以下是写入以执行在OpenFlowPlugin项目的sal-flow.yang部分中定义的RPC调用的代码。 第一步是对一个对服务项目的引用,第二步是用适当的输入执行YANG定义的函数调用。



public class TapProvider ... {
    public TapAppProvider(..) {
        this.salFlowService = rpcProviderRegistry.getRpcService(SalFlowService.class)
    }
    public void procedure1() {
        RemoveFlowInputBuilder flowBuilder = new RemoveFlowInputBuilder();
        flowBuilder.setBarrier(true);
        flowBuilder.setNode(nodeRef);
        //RPC to SAL Flow Service in OpenFlowPlugin
        salFlowService.removeFlow(flowBuilder.build());
    }
}




3.6北向和南向插件

generic-controller-architecture典型的插件是用于将OpenDaylight与外部系统集成的代码抽象。以下是应用程序开发人员需要熟悉的一些常见插件。
北向插件:两个最常用的北向插件是通过安装odl-restconf启用的RESTconf和通过安装odl-netconf-mdsal功能启用的NETCONF接口到MD-SAL。这两者都可以与意图层组合使用。
Southbound插件:OpenFlow插件(通过安装odl-openflowplugin-southbound功能启用)和NETCONF连接器(通过安装odl-netconf-connector-all功能启用)是两个常用的南向插件。
本教程的其余部分使用OpenFlow插件构建应用程序,其中OpenFlow FLOW_MOD,PACKET_IN,PACKET_OUT和其他发现操作支持作为YANG建模数据更改,通知或RPC调用。

有关使用NETCONF连接器的应用程序或示例的示例,请查看使用netconf-exercise应用程序对NETCONF进行实验的帖子。




评论

此博客中的热门博文

openflow switch(I)

YANG Tools:YANG to Java Mapping