Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

Vinllen Chen


但行好事,莫问前程

OpenDaylight中DataStore Tree Notification示例

  DataStore有三种监听事件DataChangeListener、DataTreeChangeListener和DOMDataTreeChangeListener,他们具体的区别可以参考这篇博客,本文主要介绍一下DataTreeChangeListener。DataTreeChangeListener可以用来监听整棵树或者某个子树,子树结点的改变将引发由该子节点递归到根结点整个支路结点都发生改变,原理是version号的变化,具体可以参考我之前的博客

实验

yang文件

  包含多级container的yang文件定义如下:

    container threshold {
        description "Threshold configuration";
        container temperature {
            leaf mac_temperature {
                config true;
                type int16;
                default 50;
                description
                    "Temperature threshold";
            }
            leaf cpu_temperature {
                config true;
                type int16;
                default 60;
                description
                    "Temperature threshold";
            }
        }
        container cpu {
            leaf cpu_usage {
                config true;
                type int16;
                default 50;
                description
                    "CPU usage threshold";
            }
        }

生成的REST接口

  container属于config tree,将会生成对应的rest接口,不同container嵌套存在:
rest-api

DataTreeChangeListener

  我需要对第二层container进行监听,其实可以设置两种监听事件:

  1. 对不同container数据分别监听,好处是处理比较方便,直接可以拿到更改的数据,进行处理;缺点是要是第二层container进行扩展至十多个,那么就要分别写十多个监听函数,代码不太雅观。
  2. 对根结点进行监控,然后处理监听事件,获取具体container再具体处理;好处是代码简洁一下,缺点是处理稍微复杂一下。

  第一种比较简单,具体介绍一下第二种方法。当拿到DataObjectModification对象后,有一个getModifiedChildren()可以拿到发生变化的直接子节点,注意此处是直接儿子结点,这意味着要是container层级很深,如果想通过这个方法定位到最终发生变化的container,则需要递归调用。拿到直接儿子结点后,再调用getDataBefore()getDataAfter()可以拿到变化前后的数据。

示例代码

  注册整棵树监听:

InstanceIdentifier iid = InstanceIdentifier.create(Threshold.class); //创建iid  
dataChangeReg = dataProvider.registerDataTreeChangeListener(  
                new DataTreeIdentifier<Threshold>(LogicalDatastoreType.CONFIGURATION, iid), new DataTreeChangeProc()); //注册iid对应的监听

dbSysTemp = new DBCollectSysTemp(dbService, new TemperatureModel()); //个人处理类  
dbCpuUsage = new DBCollectCpuUsage(dbService, new CpuUsageModel()); //个人处理类  

  监听代码:

    public class DataTreeChangeProc implements DataTreeChangeListener<Threshold> {
        private final Logger LOG = LoggerFactory.getLogger(Threshold.class);

        @Override
        public void onDataTreeChanged(Collection<DataTreeModification<Threshold>> changes) {
            for (DataTreeModification<Threshold> change : changes) {
                DataObjectModification<Threshold> rootNode = change.getRootNode();
                Collection<DataObjectModification<?>> modifiedChildren = rootNode.getModifiedChildren();
                for (DataObjectModification<?> modifiedChild : modifiedChildren) {
                    DataObject oldNode = modifiedChild.getDataBefore();
                    DataObject newNode = modifiedChild.getDataAfter();
                    if (modifiedChild.getModificationType() == DataObjectModification.ModificationType.WRITE) {

                        String className = newNode.getImplementedInterface().getSimpleName();
                        LOG.info("{}, {}, {}", className, oldNode, newNode);
                        switch (className) {
                            case "Temperature": {
                                Short macTemp = ((Temperature)newNode).getMacTemperature();
                                Short cpuTemp = ((Temperature)newNode).getCpuTemperature();
                                LOG.info("DataTreeChangeProc onDataTreeChanged - path {} was updated: " + 
                                        "[sys-temp-mac:{}, sys-temp-cpu: {}]",
                                        iid.child(Temperature.class), macTemp, cpuTemp);
                                dbSysTemp.setThresholdMacTemperature(macTemp);
                                dbSysTemp.setThresholdCpuTemperature(cpuTemp);
                                break;
                            }
                            case "Cpu": {
                                Short cpuUsage = ((Cpu)newNode).getCpuUsage();
                                LOG.info("DataTreeChangeProc onDataTreeChanged - path {} was updated: " + 
                                        "[cpu-usage-cpu:{}]",
                                        iid.child(Cpu.class), cpuUsage);
                                dbCpuUsage.setThresholdCpuUsage(cpuUsage);
                            }
                        }


                    }
                    else if (rootNode.getModificationType() == DataObjectModification.ModificationType.DELETE) {
                        String className = oldNode.getClass().getName();
                        switch (className) {
                            case "Temperature": {
                                Integer defaultMacTemp = DataType.THRESHOLD_SYS_TEMP_MAC;
                                Integer defaultCpuTemp = DataType.THRESHOLD_SYS_TEMP_CPU;
                                Short macTemp = ((Temperature)oldNode).getMacTemperature();
                                Short cpuTemp = ((Temperature)oldNode).getCpuTemperature();
                                LOG.info("DataTreeChangeProc onDataTreeChanged - path {} was deleted: " + 
                                        "[sys-temp-mac:{}, sys-temp-cpu: {}], set to default:[sys-temp-mac:{}, sys-temp-cpu: {}]",
                                        iid.child(Temperature.class), macTemp, cpuTemp, defaultMacTemp, defaultCpuTemp);
                                dbSysTemp.setThresholdMacTemperature(defaultMacTemp);
                                dbSysTemp.setThresholdCpuTemperature(defaultCpuTemp);
                                break;
                            }
                            case "Cpu": {
                                Short cpuUsage = ((Cpu)newNode).getCpuUsage();
                                Integer defaultCpuUsage = DataType.THRESHOLD_CPU_USAGE_CPU;
                                LOG.info("DataTreeChangeProc onDataTreeChanged - path {} was deleted: " + 
                                        "[cpu-usage-cpu:{}], set to default:[cpu-usage-cpu:{}]",
                                        iid.child(Cpu.class), cpuUsage, defaultCpuUsage);
                                dbCpuUsage.setThresholdCpuUsage(defaultCpuUsage);
                            }
                        }
                    }
                }
            }
        }
    }

  具体关于DataStore原理性介绍参考我的上一篇博客的介绍

参考

http://www.zhaoguangze.com/pages/2016/01/15/opendaylightkai-fa-3-datastorechangejian-ting-qi-san-chong-lei-xing.html
http://vinllen.com/opendaylight-datastorefen-xi/

说明

装载请注明出处:http://vinllen.com/opendaylightzhong-datastore-tree-notificationshi-li/


About the author

vinllen chen

Beijing, China

格物致知


Discussions

comments powered by Disqus