csr对象上树,采用手动上树,预处理回调返回false,仍然有自动上树对象

问题描述

function lsw_main:register_csr_object_mgmt()

    local ret = constants.RET.RET_OK

    -- 注册对象响应回调函数

    -- 添加对象回调

    object_manage.on_add_object(self.bus, function(class_name, object, position)

            self.lsw.lsw_cfg_mgmt:on_add_object(class_name, object, position)

        end, 

        function(object)

            return false

        end

    )

    -- 删除对象回调

    object_manage.on_delete_object(self.bus, function(class_name, object, position)

    end)

    -- 添加对象完成回调

    object_manage.on_add_object_complete(self.bus, function(position)

        local ret = constants.RET.RET_OK

        ret = self.lsw.lsw_cfg_mgmt:convert_csr_to_soft()

        if ret ~= constants.RET.RET_OK then

            logging:error('[on_add_object_complete] convert_csr_to_soft failed, ret(%u)', ret)

        end

        logging:notice('[register_object_mgmt] add object complete, position: %s', position)

    end)

    -- 删除对象完成回调

    object_manage.on_delete_object_complete(self.bus, function(position)

    end)

end
function lsw_cfg_mgmt:on_add_object(class_name, object, position)

    (({

        ['Port'] = function ()

            self.port_cfg_mgmt.port_attr_mgmt:add_port_object(object, position)

        end,

        ['MacInfoTable'] = function ()

            self.mac_cfg_mgmt.mac_attr:add_mac_object(object, position)

        end,

        ['ACLRuleInfo'] = function ()

            self.acl_cfg_mgmt.acl_attr_mgmt:add_all_acl_object(object, position)

        end

    })[class_name] or function() end)()

end

手动上树调用处

function port_attr_mgmt:add_port_object(obj, position)

    local ret, port_obj = constants.RET.RET_OK, nil

    local db = orm_object_manage.get_instance().per_db

    if db == nil then

        log:error("db is nil.")

    end

    local port_db = db:select(db.Port):where(db.Port.LogicPortId:eq(obj.LogicPortId)):first()

    if port_db == nil then

        db:insert(db.Port):value(obj):exec()

        local port_object = base_service:CreatePort(1, obj.LogicPortId, function(object)

            object.LogicPortId = obj.LogicPortId

            object.PortName = obj.PortName

            object.Enable = obj.Enable

        end)

    else

        log:error("%u---------------%s----------------%s   in  db", port_db.LogicPortId, port_db.PortName, tostring(port_db.Enable))

        local port_object = base_service:CreatePort(1, obj.LogicPortId, function(object)

            object.LogicPortId = port_db.LogicPortId

            object.PortName = port_db.PortName

            object.Enable = port_db.Enable

        end)

        obj = port_db

    end

    ret, port_obj = port_attr_mgmt:fetch_port_info_from_csr(obj)

    if ret == constants.RET.RET_OK and port_obj ~= nil then

        table.insert(self.ports_obj, port_obj)

        table.sort(self.ports_obj, function(a, b)

            return a.LogicPortId < b.LogicPortId

        end)

        return constants.RET.RET_OK

    else

        log:error("[add_port_object]: fetch_port_info_from_csr failed, ret(%u).", ret)

        return constants.RET.RET_ERR

    end

end

Service bmc.kepler.lsw_main:
└─/bmc
  └─/bmc/kepler
    ├─/bmc/kepler/Debug
    │ └─/bmc/kepler/Debug/LswMainDebug
    ├─/bmc/kepler/IpmiCmds
    │ └─/bmc/kepler/IpmiCmds/30
    │   └─/bmc/kepler/IpmiCmds/30/93
    │     └─/bmc/kepler/IpmiCmds/30/93/SetOtherSmmPortEnable
    ├─/bmc/kepler/Switch
    │ ├─/bmc/kepler/Switch/1
    │ │ └─/bmc/kepler/Switch/1/Ports
    │ │   ├─/bmc/kepler/Switch/1/Ports/1
    │ │   ├─/bmc/kepler/Switch/1/Ports/10
    │ │   ├─/bmc/kepler/Switch/1/Ports/11
    │ │   ├─/bmc/kepler/Switch/1/Ports/12
    │ │   ├─/bmc/kepler/Switch/1/Ports/13
    │ │   ├─/bmc/kepler/Switch/1/Ports/14
    │ │   ├─/bmc/kepler/Switch/1/Ports/15
    │ │   ├─/bmc/kepler/Switch/1/Ports/16
    │ │   ├─/bmc/kepler/Switch/1/Ports/17
    │ │   ├─/bmc/kepler/Switch/1/Ports/18
    │ │   ├─/bmc/kepler/Switch/1/Ports/19
    │ │   ├─/bmc/kepler/Switch/1/Ports/2
    │ │   ├─/bmc/kepler/Switch/1/Ports/20
    │ │   ├─/bmc/kepler/Switch/1/Ports/21
    │ │   ├─/bmc/kepler/Switch/1/Ports/22
    │ │   ├─/bmc/kepler/Switch/1/Ports/23
    │ │   ├─/bmc/kepler/Switch/1/Ports/24
    │ │   ├─/bmc/kepler/Switch/1/Ports/25
    │ │   ├─/bmc/kepler/Switch/1/Ports/26
    │ │   ├─/bmc/kepler/Switch/1/Ports/27
    │ │   ├─/bmc/kepler/Switch/1/Ports/28
    │ │   ├─/bmc/kepler/Switch/1/Ports/29
    │ │   ├─/bmc/kepler/Switch/1/Ports/3
    │ │   ├─/bmc/kepler/Switch/1/Ports/30
    │ │   ├─/bmc/kepler/Switch/1/Ports/31
    │ │   ├─/bmc/kepler/Switch/1/Ports/4
    │ │   ├─/bmc/kepler/Switch/1/Ports/5
    │ │   ├─/bmc/kepler/Switch/1/Ports/6
    │ │   ├─/bmc/kepler/Switch/1/Ports/7
    │ │   ├─/bmc/kepler/Switch/1/Ports/8
    │ │   └─/bmc/kepler/Switch/1/Ports/9
    │ ├─/bmc/kepler/Switch/Port_10_01010B
    │ │ └─/bmc/kepler/Switch/Port_10_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_10_01010B/Ports/Port_10_01010B
    │ ├─/bmc/kepler/Switch/Port_11_01010B
    │ │ └─/bmc/kepler/Switch/Port_11_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_11_01010B/Ports/Port_11_01010B
    │ ├─/bmc/kepler/Switch/Port_12_01010B
    │ │ └─/bmc/kepler/Switch/Port_12_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_12_01010B/Ports/Port_12_01010B
    │ ├─/bmc/kepler/Switch/Port_13_01010B
    │ │ └─/bmc/kepler/Switch/Port_13_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_13_01010B/Ports/Port_13_01010B
    │ ├─/bmc/kepler/Switch/Port_14_01010B
    │ │ └─/bmc/kepler/Switch/Port_14_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_14_01010B/Ports/Port_14_01010B
    │ ├─/bmc/kepler/Switch/Port_15_01010B
    │ │ └─/bmc/kepler/Switch/Port_15_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_15_01010B/Ports/Port_15_01010B
    │ ├─/bmc/kepler/Switch/Port_16_01010B
    │ │ └─/bmc/kepler/Switch/Port_16_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_16_01010B/Ports/Port_16_01010B
    │ ├─/bmc/kepler/Switch/Port_17_01010B
    │ │ └─/bmc/kepler/Switch/Port_17_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_17_01010B/Ports/Port_17_01010B
    │ ├─/bmc/kepler/Switch/Port_18_01010B
    │ │ └─/bmc/kepler/Switch/Port_18_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_18_01010B/Ports/Port_18_01010B
    │ ├─/bmc/kepler/Switch/Port_19_01010B
    │ │ └─/bmc/kepler/Switch/Port_19_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_19_01010B/Ports/Port_19_01010B
    │ ├─/bmc/kepler/Switch/Port_1_01010B
    │ │ └─/bmc/kepler/Switch/Port_1_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_1_01010B/Ports/Port_1_01010B
    │ ├─/bmc/kepler/Switch/Port_20_01010B
    │ │ └─/bmc/kepler/Switch/Port_20_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_20_01010B/Ports/Port_20_01010B
    │ ├─/bmc/kepler/Switch/Port_21_01010B
    │ │ └─/bmc/kepler/Switch/Port_21_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_21_01010B/Ports/Port_21_01010B
    │ ├─/bmc/kepler/Switch/Port_22_01010B
    │ │ └─/bmc/kepler/Switch/Port_22_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_22_01010B/Ports/Port_22_01010B
    │ ├─/bmc/kepler/Switch/Port_23_01010B
    │ │ └─/bmc/kepler/Switch/Port_23_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_23_01010B/Ports/Port_23_01010B
    │ ├─/bmc/kepler/Switch/Port_24_01010B
    │ │ └─/bmc/kepler/Switch/Port_24_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_24_01010B/Ports/Port_24_01010B
    │ ├─/bmc/kepler/Switch/Port_25_01010B
    │ │ └─/bmc/kepler/Switch/Port_25_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_25_01010B/Ports/Port_25_01010B
    │ ├─/bmc/kepler/Switch/Port_26_01010B
    │ │ └─/bmc/kepler/Switch/Port_26_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_26_01010B/Ports/Port_26_01010B
    │ ├─/bmc/kepler/Switch/Port_27_01010B
    │ │ └─/bmc/kepler/Switch/Port_27_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_27_01010B/Ports/Port_27_01010B
    │ ├─/bmc/kepler/Switch/Port_28_01010B
    │ │ └─/bmc/kepler/Switch/Port_28_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_28_01010B/Ports/Port_28_01010B
    │ ├─/bmc/kepler/Switch/Port_29_01010B
    │ │ └─/bmc/kepler/Switch/Port_29_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_29_01010B/Ports/Port_29_01010B
    │ ├─/bmc/kepler/Switch/Port_2_01010B
    │ │ └─/bmc/kepler/Switch/Port_2_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_2_01010B/Ports/Port_2_01010B
    │ ├─/bmc/kepler/Switch/Port_30_01010B
    │ │ └─/bmc/kepler/Switch/Port_30_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_30_01010B/Ports/Port_30_01010B
    │ ├─/bmc/kepler/Switch/Port_31_01010B
    │ │ └─/bmc/kepler/Switch/Port_31_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_31_01010B/Ports/Port_31_01010B
    │ ├─/bmc/kepler/Switch/Port_3_01010B
    │ │ └─/bmc/kepler/Switch/Port_3_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_3_01010B/Ports/Port_3_01010B
    │ ├─/bmc/kepler/Switch/Port_4_01010B
    │ │ └─/bmc/kepler/Switch/Port_4_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_4_01010B/Ports/Port_4_01010B
    │ ├─/bmc/kepler/Switch/Port_5_01010B
    │ │ └─/bmc/kepler/Switch/Port_5_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_5_01010B/Ports/Port_5_01010B
    │ ├─/bmc/kepler/Switch/Port_6_01010B
    │ │ └─/bmc/kepler/Switch/Port_6_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_6_01010B/Ports/Port_6_01010B
    │ ├─/bmc/kepler/Switch/Port_7_01010B
    │ │ └─/bmc/kepler/Switch/Port_7_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_7_01010B/Ports/Port_7_01010B
    │ ├─/bmc/kepler/Switch/Port_8_01010B
    │ │ └─/bmc/kepler/Switch/Port_8_01010B/Ports
    │ │   └─/bmc/kepler/Switch/Port_8_01010B/Ports/Port_8_01010B
    │ └─/bmc/kepler/Switch/Port_9_01010B
    │   └─/bmc/kepler/Switch/Port_9_01010B/Ports
    │     └─/bmc/kepler/Switch/Port_9_01010B/Ports/Port_9_01010B
    └─/bmc/kepler/lsw_main
      └─/bmc/kepler/lsw_main/MicroComponent
        └─/bmc/kepler/lsw_main/MicroComponent/Debug

答案内容由AI生成,仅供参考:

总结

当前问题本质是对象生命周期管理混乱所致。虽然预处理回调返回false可阻止CSR自动上树,但由于手动创建逻辑未做充分去重保护,且可能与框架其他机制交互异常,导致仍出现意料之外的对象。建议采用ORM统一管理 + 精确回调控制 + 路径定制化的组合策略,从根本上杜绝重复上树问题。

点击此处查看详细分析解答

CSR对象手动上树问题分析

问题描述

用户在实现CSR对象手动上树时,尽管在object_manage.on_add_object的预处理回调中返回了false(意图取消CSR自动上树),但系统中仍然出现了自动上树的对象,导致同一资源存在重复对象的问题。

根源分析

手动上树与自动上树的机制冲突

根据知识库内容和代码逻辑分析,出现问题的根本原因如下:

  1. 预处理回调返回 false 的作用

    • 当预处理回调函数返回 false 时,确实会阻止CSR自动上树流程。
    • 文档明确指出:第三个参数返回false,会取消CSR自动上树
  2. 对象创建流程未完全隔离

    • 尽管自动上树被取消,但object_manage.on_add_object的主回调函数仍会被执行。
    • 在该回调中调用了self.lsw.lsw_cfg_mgmt:on_add_object,进而触发add_port_object等方法进行手动上树。
    • 关键问题:手动创建对象的逻辑(base_service:CreatePort)与CSR对象管理系统的自发现机制混合使用,容易造成对象重复。
  3. 潜在重复对象风险

    • 如社区专家chenghaoyang所指出:“你再调CreateXXX方法会造成你实际上有两个对象”。
    • 这意味着即使自动上树被阻止,手动创建流程若未正确控制条件,仍可能导致对象重复实例化。

解决方案建议

方案一:确保唯一性判断

add_port_object方法中加强对象存在性检查:

function port_attr_mgmt:add_port_object(obj, position)
    -- 检查资源树是否已存在相同LogicPortId的对象
    local existing_obj = self:get_port_by_logic_id(obj.LogicPortId)
    if existing_obj then
        log:warn("Port with LogicPortId %d already exists, skip duplicate creation", obj.LogicPortId)
        return constants.RET.RET_OK
    end
    
    -- ... 原有创建逻辑 ...
end

方案二:优化回调设计

确保只有在真正需要时才进行手动上树:

object_manage.on_add_object(self.bus, 
    function(class_name, object, position)
        -- 仅处理特定类别的对象
        if class_name == 'Port' then
            self.lsw.lsw_cfg_mgmt:on_add_object(class_name, object, position)
        end
    end, 
    function(object)
        -- 明确拒绝自动上树
        return false  -- 确保返回false阻止默认行为
    end
)

方案三:使用ORM特性统一管理(推荐)

启用ORM自动持久化,避免手动插入数据库与手动创建对象并行操作带来的不一致:

-- 在组件初始化时启动ORM
local orm_object_manage = require 'mc.orm.object_manage'
orm_object_manage.get_instance(self.db, self.bus):start()

-- 在预处理回调中补全主键,交由框架恢复数据
object_manage.on_add_object(self.bus, 
    function(class_name, object, position)
        -- 框架已自动恢复持久化数据
        self.lsw.lsw_cfg_mgmt:on_add_object(class_name, object, position)
    end,
    function(object)
        -- 补全主键信息用于匹配持久化数据
        if object.class_name == "Port" then
            object.LogicPortId = object.LogicPortId -- 主键
            object.PortName = object.PortName       -- 主键
        end
        return false -- 继续手动上树控制
    end
)

最佳实践建议

  1. 避免混用模式:不要同时使用“手动CreatePort”和“自发现+回调处理”,应选择一种统一的对象管理范式。

  2. 路径控制:对于动态路径/bmc/kepler/Switch/:id/Ports/:ID,可通过修改on_add_object中的object.path来定制实际路径,如chenghaoyang建议:“你可以直接修改on_add_object获取的object的path”。

  3. 调试验证

    • 使用 busctl tree bmc.kepler 查看资源树结构,确认无重复节点。
    • 检查日志是否出现多次add_port_object调用记录。

总结

当前问题本质是对象生命周期管理混乱所致。虽然预处理回调返回false可阻止CSR自动上树,但由于手动创建逻辑未做充分去重保护,且可能与框架其他机制交互异常,导致仍出现意料之外的对象。建议采用ORM统一管理 + 精确回调控制 + 路径定制化的组合策略,从根本上杜绝重复上树问题。

CSR配置是什么样的